
Recherche avancée
Médias (2)
-
Core Media Video
4 avril 2013, par
Mis à jour : Juin 2013
Langue : français
Type : Video
-
Video d’abeille en portrait
14 mai 2011, par
Mis à jour : Février 2012
Langue : français
Type : Video
Autres articles (15)
-
Encoding and processing into web-friendly formats
13 avril 2011, parMediaSPIP automatically converts uploaded files to internet-compatible formats.
Video files are encoded in MP4, Ogv and WebM (supported by HTML5) and MP4 (supported by Flash).
Audio files are encoded in MP3 and Ogg (supported by HTML5) and MP3 (supported by Flash).
Where possible, text is analyzed in order to retrieve the data needed for search engine detection, and then exported as a series of image files.
All uploaded files are stored online in their original format, so you can (...) -
Keeping control of your media in your hands
13 avril 2011, parThe vocabulary used on this site and around MediaSPIP in general, aims to avoid reference to Web 2.0 and the companies that profit from media-sharing.
While using MediaSPIP, you are invited to avoid using words like "Brand", "Cloud" and "Market".
MediaSPIP is designed to facilitate the sharing of creative media online, while allowing authors to retain complete control of their work.
MediaSPIP aims to be accessible to as many people as possible and development is based on expanding the (...) -
Other interesting software
13 avril 2011, parWe don’t claim to be the only ones doing what we do ... and especially not to assert claims to be the best either ... What we do, we just try to do it well and getting better ...
The following list represents softwares that tend to be more or less as MediaSPIP or that MediaSPIP tries more or less to do the same, whatever ...
We don’t know them, we didn’t try them, but you can take a peek.
Videopress
Website : http://videopress.com/
License : GNU/GPL v2
Source code : (...)
Sur d’autres sites (3637)
-
FFmpeg "movflags" > "faststart" causes invalid MP4 file to be written
22 août 2016, par williamtroupI’m setting up the format layout for the video as follows :
AVOutputFormat* outputFormat = ffmpeg.av_guess_format(null, "output.mp4", null);
AVCodec* videoCodec = ffmpeg.avcodec_find_encoder(outputFormat->video_codec);
AVFormatContext* formatContext = ffmpeg.avformat_alloc_context();
formatContext->oformat = outputFormat;
formatContext->video_codec_id = videoCodec->id;
ffmpeg.avformat_new_stream(formatContext, videoCodec);This is how I am setting up the Codec Context :
AVCodecContext* codecContext = ffmpeg.avcodec_alloc_context3(videoCodec);
codecContext->bit_rate = 400000;
codecContext->width = 1280;
codecContext->height = 720;
codecContext->gop_size = 12;
codecContext->max_b_frames = 1;
codecContext->pix_fmt = videoCodec->pix_fmts[0];
codecContext->codec_id = videoCodec->id;
codecContext->codec_type = videoCodec->type;
codecContext->time_base = new AVRational
{
num = 1,
den = 30
};I’m using the following code to setup the "movflags" > "faststart" option for the header of the video :
AVDictionary* options = null;
int result = ffmpeg.av_dict_set(&options, "movflags", "faststart", 0);
int writeHeaderResult = ffmpeg.avformat_write_header(formatContext, &options);The file is opened and the header is written as follows :
if ((formatContext->oformat->flags & ffmpeg.AVFMT_NOFILE) == 0)
{
int ioOptionResult = ffmpeg.avio_open(&formatContext->pb, "output.mp4", ffmpeg.AVIO_FLAG_WRITE);
}
int writeHeaderResult = ffmpeg.avformat_write_header(formatContext, &options);After this, I write each video frame as follows :
outputFrame->pts = frameIndex;
packet.flags |= ffmpeg.AV_PKT_FLAG_KEY;
packet.pts = frameIndex;
packet.dts = frameIndex;
int encodedFrame = 0;
int encodeVideoResult = ffmpeg.avcodec_encode_video2(codecContext, &packet, outputFrame, &encodedFrame);
if (encodedFrame != 0)
{
packet.pts = ffmpeg.av_rescale_q(packet.pts, codecContext->time_base, m_videoStream->time_base);
packet.dts = ffmpeg.av_rescale_q(packet.dts, codecContext->time_base, m_videoStream->time_base);
packet.stream_index = m_videoStream->index;
if (codecContext->coded_frame->key_frame > 0)
{
packet.flags |= ffmpeg.AV_PKT_FLAG_KEY;
}
int writeFrameResult = ffmpeg.av_interleaved_write_frame(formatContext, &packet);
}After that, I write the trailer :
int writeTrailerResult = ffmpeg.av_write_trailer(formatContext);
The file finishes writing and everything closes and frees up correctly. However, the MP4 file is unplayable (even VLC cant play it). AtomicParsley.exe won’t show any information about the file either.
The DLLs used for the AutoGen library are :
avcodec-56.dll
avdevice-56.dll
avfilter-5.dll
avformat-56.dll
avutil-54.dll
postproc-53.dll
swresample-1.dll
swscale-3.dll -
ffmpeg error "Could not allocate picture : Invalid argument Found Video Stream Found Audio Stream"
26 octobre 2020, par DinkanI am trying to write a C program to stream AV by copying both AV codecs with
rtp_mpegts
using RTP over network

ffmpeg -re -i Sample_AV_15min.ts -acodec copy -vcodec copy -f rtp_mpegts rtp://192.168.1.1:5004



using muxing.c as example which used ffmpeg libraries.
ffmpeg application works fine.


Stream details


Input #0, mpegts, from 'Weather_Nation_10min.ts':
 Duration: 00:10:00.38, start: 41313.400811, bitrate: 2840 kb/s
 Program 1
 Stream #0:0[0x11]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p, 1440x1080 [SAR 4:3 DAR 16:9], 29.97 fps, 59.94 tbr, 90k tbn, 59.94 tbc
 Stream #0:1[0x14]: Audio: ac3 (AC-3 / 0x332D4341), 48000 Hz, stereo, fltp, 448 kb/s
Output #0, rtp_mpegts, to 'rtp://192.168.1.1:5004':
 Metadata:
 encoder : Lavf54.63.104
 Stream #0:0: Video: h264 ([27][0][0][0] / 0x001B), yuv420p, 1440x1080 [SAR 4:3 DAR 16:9], q=2-31, 29.97 fps, 90k tbn, 29.97 tbc
 Stream #0:1: Audio: ac3 (AC-3 / 0x332D4341), 48000 Hz, stereo, 448 kb/s
Stream mapping:
 Stream #0:0 -> #0:0 (copy)
 Stream #0:1 -> #0:1 (copy)



However, my application fails with


./my_test_app Sample_AV_15min.ts rtp://192.168.1.1:5004 
[h264 @ 0x800b30] non-existing PPS referenced 
[h264 @ 0x800b30] non-existing PPS 0 referenced 
[h264 @ 0x800b30] decode_slice_header error 
[h264 @ 0x800b30] no frame! 

[....snipped...]
[h264 @ 0x800b30] non-existing PPS 0 referenced 
[h264 @ 0x800b30] non-existing PPS referenced 
[h264 @ 0x800b30] non-existing PPS 0 referenced 
[h264 @ 0x800b30] decode_slice_header error 
[h264 @ 0x800b30] no frame! 
[h264 @ 0x800b30] mmco: unref short failure 
[h264 @ 0x800b30] mmco: unref short failure

[mpegts @ 0x800020] max_analyze_duration 5000000 reached at 5024000 microseconds 
[mpegts @ 0x800020] PES packet size mismatch could not find codec tag for codec id 
17075200, default to 0. could not find codec tag for codec id 86019, default to 0. 
Could not allocate picture: Invalid argument 
Found Video Stream Found Audio Stream



How do I fix this ? My complete source code based on muxing.c


/**
 * @file
 * libavformat API example.
 *
 * Output a media file in any supported libavformat format.
 * The default codecs are used.
 * @example doc/examples/muxing.c
 */

#include 
#include 
#include 
#include 

#include <libavutil></libavutil>mathematics.h>
#include <libavformat></libavformat>avformat.h>
#include <libswscale></libswscale>swscale.h>

/* 5 seconds stream duration */
#define STREAM_DURATION 200.0
#define STREAM_FRAME_RATE 25 /* 25 images/s */
#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */

static int sws_flags = SWS_BICUBIC;

/**************************************************************/
/* audio output */

static float t, tincr, tincr2;
static int16_t *samples;
static int audio_input_frame_size;
#if 0
/* Add an output stream. */
static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,
 enum AVCodecID codec_id)
{
 AVCodecContext *c;
 AVStream *st;

 /* find the encoder */
 *codec = avcodec_find_encoder(codec_id);
 if (!(*codec)) {
 fprintf(stderr, "Could not find encoder for '%s'\n",
 avcodec_get_name(codec_id));
 exit(1);
 }

 st = avformat_new_stream(oc, *codec);
 if (!st) {
 fprintf(stderr, "Could not allocate stream\n");
 exit(1);
 }
 st->id = oc->nb_streams-1;
 c = st->codec;

 switch ((*codec)->type) {
 case AVMEDIA_TYPE_AUDIO:
 st->id = 1;
 c->sample_fmt = AV_SAMPLE_FMT_S16;
 c->bit_rate = 64000;
 c->sample_rate = 44100;
 c->channels = 2;
 break;

 case AVMEDIA_TYPE_VIDEO:
 c->codec_id = codec_id;

 c->bit_rate = 400000;
 /* Resolution must be a multiple of two. */
 c->width = 352;
 c->height = 288;
 /* timebase: This is the fundamental unit of time (in seconds) in terms
 * of which frame timestamps are represented. For fixed-fps content,
 * timebase should be 1/framerate and timestamp increments should be
 * identical to 1. */
 c->time_base.den = STREAM_FRAME_RATE;
 c->time_base.num = 1;
 c->gop_size = 12; /* emit one intra frame every twelve frames at most */
 c->pix_fmt = STREAM_PIX_FMT;
 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
 /* just for testing, we also add B frames */
 c->max_b_frames = 2;
 }
 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
 /* Needed to avoid using macroblocks in which some coeffs overflow.
 * This does not happen with normal video, it just happens here as
 * the motion of the chroma plane does not match the luma plane. */
 c->mb_decision = 2;
 }
 break;

 default:
 break;
 }

 /* Some formats want stream headers to be separate. */
 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
 c->flags |= CODEC_FLAG_GLOBAL_HEADER;

 return st;
}
#endif 
/**************************************************************/
/* audio output */

static float t, tincr, tincr2;
static int16_t *samples;
static int audio_input_frame_size;

static void open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st)
{
 AVCodecContext *c;
 int ret;

 c = st->codec;

 /* open it */
 ret = avcodec_open2(c, codec, NULL);
 if (ret < 0) {
 fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
 exit(1);
 }

 /* init signal generator */
 t = 0;
 tincr = 2 * M_PI * 110.0 / c->sample_rate;
 /* increment frequency by 110 Hz per second */
 tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;

 if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
 audio_input_frame_size = 10000;
 else
 audio_input_frame_size = c->frame_size;
 samples = av_malloc(audio_input_frame_size *
 av_get_bytes_per_sample(c->sample_fmt) *
 c->channels);
 if (!samples) {
 fprintf(stderr, "Could not allocate audio samples buffer\n");
 exit(1);
 }
}

/* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
 * 'nb_channels' channels. */
static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
{
 int j, i, v;
 int16_t *q;

 q = samples;
 for (j = 0; j < frame_size; j++) {
 v = (int)(sin(t) * 10000);
 for (i = 0; i < nb_channels; i++)
 *q++ = v;
 t += tincr;
 tincr += tincr2;
 }
}

static void write_audio_frame(AVFormatContext *oc, AVStream *st)
{
 AVCodecContext *c;
 AVPacket pkt = { 0 }; // data and size must be 0;
 AVFrame *frame = avcodec_alloc_frame();
 int got_packet, ret;

 av_init_packet(&pkt);
 c = st->codec;

 get_audio_frame(samples, audio_input_frame_size, c->channels);
 frame->nb_samples = audio_input_frame_size;
 avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
 (uint8_t *)samples,
 audio_input_frame_size *
 av_get_bytes_per_sample(c->sample_fmt) *
 c->channels, 1);

 ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
 if (ret < 0) {
 fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
 exit(1);
 }

 if (!got_packet)
 return;

 pkt.stream_index = st->index;

 /* Write the compressed frame to the media file. */
 ret = av_interleaved_write_frame(oc, &pkt);
 if (ret != 0) {
 fprintf(stderr, "Error while writing audio frame: %s\n",
 av_err2str(ret));
 exit(1);
 }
 avcodec_free_frame(&frame);
}

static void close_audio(AVFormatContext *oc, AVStream *st)
{
 avcodec_close(st->codec);

 av_free(samples);
}

/**************************************************************/
/* video output */

static AVFrame *frame;
static AVPicture src_picture, dst_picture;
static int frame_count;

static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st)
{
 int ret;
 AVCodecContext *c = st->codec;

 /* open the codec */
 ret = avcodec_open2(c, codec, NULL);
 if (ret < 0) {
 fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
 exit(1);
 }

 /* allocate and init a re-usable frame */
 frame = avcodec_alloc_frame();
 if (!frame) {
 fprintf(stderr, "Could not allocate video frame\n");
 exit(1);
 }

 /* Allocate the encoded raw picture. */
 ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height);
 if (ret < 0) {
 fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret));
 exit(1);
 }

 /* If the output format is not YUV420P, then a temporary YUV420P
 * picture is needed too. It is then converted to the required
 * output format. */
 if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
 ret = avpicture_alloc(&src_picture, AV_PIX_FMT_YUV420P, c->width, c->height);
 if (ret < 0) {
 fprintf(stderr, "Could not allocate temporary picture: %s\n",
 av_err2str(ret));
 exit(1);
 }
 }

 /* copy data and linesize picture pointers to frame */
 *((AVPicture *)frame) = dst_picture;
}

/* Prepare a dummy image. */
static void fill_yuv_image(AVPicture *pict, int frame_index,
 int width, int height)
{
 int x, y, i;

 i = frame_index;

 /* Y */
 for (y = 0; y < height; y++)
 for (x = 0; x < width; x++)
 pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;

 /* Cb and Cr */
 for (y = 0; y < height / 2; y++) {
 for (x = 0; x < width / 2; x++) {
 pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
 pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
 }
 }
}

static void write_video_frame(AVFormatContext *oc, AVStream *st)
{
 int ret;
 static struct SwsContext *sws_ctx;
 AVCodecContext *c = st->codec;

 if (frame_count >= STREAM_NB_FRAMES) {
 /* No more frames to compress. The codec has a latency of a few
 * frames if using B-frames, so we get the last frames by
 * passing the same picture again. */
 } else {
 if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
 /* as we only generate a YUV420P picture, we must convert it
 * to the codec pixel format if needed */
 if (!sws_ctx) {
 sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_YUV420P,
 c->width, c->height, c->pix_fmt,
 sws_flags, NULL, NULL, NULL);
 if (!sws_ctx) {
 fprintf(stderr,
 "Could not initialize the conversion context\n");
 exit(1);
 }
 }
 fill_yuv_image(&src_picture, frame_count, c->width, c->height);
 sws_scale(sws_ctx,
 (const uint8_t * const *)src_picture.data, src_picture.linesize,
 0, c->height, dst_picture.data, dst_picture.linesize);
 } else {
 fill_yuv_image(&dst_picture, frame_count, c->width, c->height);
 }
 }

 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
 /* Raw video case - directly store the picture in the packet */
 AVPacket pkt;
 av_init_packet(&pkt);

 pkt.flags |= AV_PKT_FLAG_KEY;
 pkt.stream_index = st->index;
 pkt.data = dst_picture.data[0];
 pkt.size = sizeof(AVPicture);

 ret = av_interleaved_write_frame(oc, &pkt);
 } else {
 /* encode the image */
 AVPacket pkt;
 int got_output;

 av_init_packet(&pkt);
 pkt.data = NULL; // packet data will be allocated by the encoder
 pkt.size = 0;

 ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
 if (ret < 0) {
 fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
 exit(1);
 }

 /* If size is zero, it means the image was buffered. */
 if (got_output) {
 if (c->coded_frame->key_frame)
 pkt.flags |= AV_PKT_FLAG_KEY;

 pkt.stream_index = st->index;

 /* Write the compressed frame to the media file. */
 ret = av_interleaved_write_frame(oc, &pkt);
 } else {
 ret = 0;
 }
 }
 if (ret != 0) {
 fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
 exit(1);
 }
 frame_count++;
}

static void close_video(AVFormatContext *oc, AVStream *st)
{
 avcodec_close(st->codec);
 av_free(src_picture.data[0]);
 av_free(dst_picture.data[0]);
 av_free(frame);
}

/**************************************************************/
/* media file output */

int main(int argc, char **argv)
{
 const char *filename;
 AVOutputFormat *fmt;
 AVFormatContext *oc;
 AVStream *audio_st, *video_st;
 AVCodec *audio_codec, *video_codec;
 double audio_pts, video_pts;
 int ret;
 char errbuf[50];
 int i = 0;
 /* Initialize libavcodec, and register all codecs and formats. */
 av_register_all();

 if (argc != 3) {
 printf("usage: %s input_file out_file|stream\n"
 "API example program to output a media file with libavformat.\n"
 "This program generates a synthetic audio and video stream, encodes and\n"
 "muxes them into a file named output_file.\n"
 "The output format is automatically guessed according to the file extension.\n"
 "Raw images can also be output by using '%%d' in the filename.\n"
 "\n", argv[0]);
 return 1;
 }

 filename = argv[2];

 /* allocate the output media context */
 avformat_alloc_output_context2(&oc, NULL, "rtp_mpegts", filename);
 if (!oc) {
 printf("Could not deduce output format from file extension: using MPEG.\n");
 avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
 }
 if (!oc) {
 return 1;
 }
 fmt = oc->oformat;
 //Find input stream info.

 video_st = NULL;
 audio_st = NULL;

 avformat_open_input( &oc, argv[1], 0, 0);

 if ((ret = avformat_find_stream_info(oc, 0))< 0)
 {
 av_strerror(ret, errbuf,sizeof(errbuf));
 printf("Not Able to find stream info::%s ", errbuf);
 ret = -1;
 return ret;
 }
 for (i = 0; i < oc->nb_streams; i++)
 {
 if(oc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 {
 AVCodecContext *codec_ctx;
 unsigned int tag = 0;

 printf("Found Video Stream ");
 video_st = oc->streams[i];
 codec_ctx = video_st->codec;
 // m_num_frames = oc->streams[i]->nb_frames;
 video_codec = avcodec_find_decoder(codec_ctx->codec_id);
 ret = avcodec_open2(codec_ctx, video_codec, NULL);
 if (ret < 0) 
 {
 av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
 return ret;
 }
 if (av_codec_get_tag2(oc->oformat->codec_tag, video_codec->id, &tag) == 0) 
 {
 av_log(NULL, AV_LOG_ERROR, "could not find codec tag for codec id %d, default to 0.\n", audio_codec->id);
 }
 video_st->codec = avcodec_alloc_context3(video_codec);
 video_st->codec->codec_tag = tag;
 }

 if(oc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 {
 AVCodecContext *codec_ctx;
 unsigned int tag = 0;

 printf("Found Audio Stream ");
 audio_st = oc->streams[i];
 // aud_dts = audio_st->cur_dts;
 // aud_pts = audio_st->last_IP_pts; 
 codec_ctx = audio_st->codec;
 audio_codec = avcodec_find_decoder(codec_ctx->codec_id);
 ret = avcodec_open2(codec_ctx, audio_codec, NULL);
 if (ret < 0) 
 {
 av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
 return ret;
 }
 if (av_codec_get_tag2(oc->oformat->codec_tag, audio_codec->id, &tag) == 0) 
 {
 av_log(NULL, AV_LOG_ERROR, "could not find codec tag for codec id %d, default to 0.\n", audio_codec->id);
 }
 audio_st->codec = avcodec_alloc_context3(audio_codec);
 audio_st->codec->codec_tag = tag;
 }
 }
 /* Add the audio and video streams using the default format codecs
 * and initialize the codecs. */
 /*
 if (fmt->video_codec != AV_CODEC_ID_NONE) {
 video_st = add_stream(oc, &video_codec, fmt->video_codec);
 }
 if (fmt->audio_codec != AV_CODEC_ID_NONE) {
 audio_st = add_stream(oc, &audio_codec, fmt->audio_codec);
 }
 */

 /* Now that all the parameters are set, we can open the audio and
 * video codecs and allocate the necessary encode buffers. */
 if (video_st)
 open_video(oc, video_codec, video_st);
 if (audio_st)
 open_audio(oc, audio_codec, audio_st);

 av_dump_format(oc, 0, filename, 1);

 /* open the output file, if needed */
 if (!(fmt->flags & AVFMT_NOFILE)) {
 ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
 if (ret < 0) {
 fprintf(stderr, "Could not open '%s': %s\n", filename,
 av_err2str(ret));
 return 1;
 }
 }

 /* Write the stream header, if any. */
 ret = avformat_write_header(oc, NULL);
 if (ret < 0) {
 fprintf(stderr, "Error occurred when opening output file: %s\n",
 av_err2str(ret));
 return 1;
 }

 if (frame)
 frame->pts = 0;
 for (;;) {
 /* Compute current audio and video time. */
 if (audio_st)
 audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
 else
 audio_pts = 0.0;

 if (video_st)
 video_pts = (double)video_st->pts.val * video_st->time_base.num /
 video_st->time_base.den;
 else
 video_pts = 0.0;

 if ((!audio_st || audio_pts >= STREAM_DURATION) &&
 (!video_st || video_pts >= STREAM_DURATION))
 break;

 /* write interleaved audio and video frames */
 if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
 write_audio_frame(oc, audio_st);
 } else {
 write_video_frame(oc, video_st);
 frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
 }
 }

 /* Write the trailer, if any. The trailer must be written before you
 * close the CodecContexts open when you wrote the header; otherwise
 * av_write_trailer() may try to use memory that was freed on
 * av_codec_close(). */
 av_write_trailer(oc);

 /* Close each codec. */
 if (video_st)
 close_video(oc, video_st);
 if (audio_st)
 close_audio(oc, audio_st);

 if (!(fmt->flags & AVFMT_NOFILE))
 /* Close the output file. */
 avio_close(oc->pb);

 /* free the stream */
 avformat_free_context(oc);

 return 0;
}



-
How to reparse video with stable "overall bit rate" ? (FFmpeg)
20 février 2018, par user3360601I have such code below :
#include
#include
#include
extern "C"
{
#include <libavcodec></libavcodec>avcodec.h>
#include <libavformat></libavformat>avformat.h>
#include <libavfilter></libavfilter>buffersink.h>
#include <libavfilter></libavfilter>buffersrc.h>
#include <libavutil></libavutil>opt.h>
#include <libavutil></libavutil>pixdesc.h>
}
static AVFormatContext *ifmt_ctx;
static AVFormatContext *ofmt_ctx;
typedef struct StreamContext {
AVCodecContext *dec_ctx;
AVCodecContext *enc_ctx;
} StreamContext;
static StreamContext *stream_ctx;
static int open_input_file(const char *filename)
{
int ret;
unsigned int i;
ifmt_ctx = NULL;
if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");
return ret;
}
if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");
return ret;
}
stream_ctx = (StreamContext *) av_mallocz_array(ifmt_ctx->nb_streams, sizeof(*stream_ctx));
if (!stream_ctx)
return AVERROR(ENOMEM);
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
AVStream *stream = ifmt_ctx->streams[i];
AVCodec *dec = avcodec_find_decoder(stream->codecpar->codec_id);
AVCodecContext *codec_ctx;
if (!dec) {
av_log(NULL, AV_LOG_ERROR, "Failed to find decoder for stream #%u\n", i);
return AVERROR_DECODER_NOT_FOUND;
}
codec_ctx = avcodec_alloc_context3(dec);
if (!codec_ctx) {
av_log(NULL, AV_LOG_ERROR, "Failed to allocate the decoder context for stream #%u\n", i);
return AVERROR(ENOMEM);
}
ret = avcodec_parameters_to_context(codec_ctx, stream->codecpar);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to copy decoder parameters to input decoder context "
"for stream #%u\n", i);
return ret;
}
/* Reencode video & audio and remux subtitles etc. */
if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
|| codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
codec_ctx->framerate = av_guess_frame_rate(ifmt_ctx, stream, NULL);
/* Open decoder */
ret = avcodec_open2(codec_ctx, dec, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
return ret;
}
}
stream_ctx[i].dec_ctx = codec_ctx;
}
av_dump_format(ifmt_ctx, 0, filename, 0);
return 0;
}
static int open_output_file(const char *filename)
{
AVStream *out_stream;
AVStream *in_stream;
AVCodecContext *dec_ctx, *enc_ctx;
AVCodec *encoder;
int ret;
unsigned int i;
ofmt_ctx = NULL;
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
if (!ofmt_ctx) {
av_log(NULL, AV_LOG_ERROR, "Could not create output context\n");
return AVERROR_UNKNOWN;
}
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) {
av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");
return AVERROR_UNKNOWN;
}
in_stream = ifmt_ctx->streams[i];
dec_ctx = stream_ctx[i].dec_ctx;
//ofmt_ctx->bit_rate = ifmt_ctx->bit_rate;
ofmt_ctx->duration = ifmt_ctx->duration;
if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
|| dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
/* in this example, we choose transcoding to same codec */
encoder = avcodec_find_encoder(dec_ctx->codec_id);
if (!encoder) {
av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n");
return AVERROR_INVALIDDATA;
}
enc_ctx = avcodec_alloc_context3(encoder);
if (!enc_ctx) {
av_log(NULL, AV_LOG_FATAL, "Failed to allocate the encoder context\n");
return AVERROR(ENOMEM);
}
/* In this example, we transcode to same properties (picture size,
* sample rate etc.). These properties can be changed for output
* streams easily using filters */
if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
enc_ctx->gop_size = dec_ctx->gop_size;
enc_ctx->bit_rate = dec_ctx->bit_rate;
enc_ctx->height = dec_ctx->height;
enc_ctx->width = dec_ctx->width;
enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;
/* take first format from list of supported formats */
if (encoder->pix_fmts)
enc_ctx->pix_fmt = encoder->pix_fmts[0];
else
enc_ctx->pix_fmt = dec_ctx->pix_fmt;
/* video time_base can be set to whatever is handy and supported by encoder */
enc_ctx->time_base = av_inv_q(dec_ctx->framerate);
enc_ctx->framerate = av_guess_frame_rate(ifmt_ctx, in_stream, NULL);
}
else {
enc_ctx->gop_size = dec_ctx->gop_size;
enc_ctx->bit_rate = dec_ctx->bit_rate;
enc_ctx->sample_rate = dec_ctx->sample_rate;
enc_ctx->channel_layout = dec_ctx->channel_layout;
enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);
/* take first format from list of supported formats */
enc_ctx->sample_fmt = encoder->sample_fmts[0];
//enc_ctx->time_base = (AVRational){ 1, enc_ctx->sample_rate };
enc_ctx->time_base.num = 1;
enc_ctx->time_base.den = enc_ctx->sample_rate;
enc_ctx->framerate = av_guess_frame_rate(ifmt_ctx, in_stream, NULL);
}
/* Third parameter can be used to pass settings to encoder */
ret = avcodec_open2(enc_ctx, encoder, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);
return ret;
}
ret = avcodec_parameters_from_context(out_stream->codecpar, enc_ctx);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to copy encoder parameters to output stream #%u\n", i);
return ret;
}
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
out_stream->time_base = enc_ctx->time_base;
stream_ctx[i].enc_ctx = enc_ctx;
}
else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {
av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);
return AVERROR_INVALIDDATA;
}
else {
/* if this stream must be remuxed */
ret = avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Copying parameters for stream #%u failed\n", i);
return ret;
}
out_stream->time_base = in_stream->time_base;
}
}
av_dump_format(ofmt_ctx, 0, filename, 1);
if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not open output file '%s'", filename);
return ret;
}
}
/* init muxer, write output file header */
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");
return ret;
}
return 0;
}
int main(int argc, char **argv)
{
int ret;
AVPacket packet = {0};
packet.data = NULL;
packet.size = 0 ;
AVFrame *frame = NULL;
enum AVMediaType type;
unsigned int stream_index;
unsigned int i;
int got_frame;
int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
if (argc != 3) {
av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file="file" /> <output file="file">\n", argv[0]);
return 1;
}
av_register_all();
avfilter_register_all();
if ((ret = open_input_file(argv[1])) < 0)
goto end;
if ((ret = open_output_file(argv[2])) < 0)
goto end;
/* read all packets */
while (1) {
if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)
break;
stream_index = packet.stream_index;
type = ifmt_ctx->streams[packet.stream_index]->codecpar->codec_type;
av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n", stream_index);
/* remux this frame without reencoding */
av_packet_rescale_ts(&packet,
ifmt_ctx->streams[stream_index]->time_base,
ofmt_ctx->streams[stream_index]->time_base);
ret = av_interleaved_write_frame(ofmt_ctx, &packet);
if (ret < 0)
goto end;
av_packet_unref(&packet);
}
av_write_trailer(ofmt_ctx);
end:
av_packet_unref(&packet);
av_frame_free(&frame);
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
avcodec_free_context(&stream_ctx[i].dec_ctx);
if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && stream_ctx[i].enc_ctx)
avcodec_free_context(&stream_ctx[i].enc_ctx);
}
av_free(stream_ctx);
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
return ret ? 1 : 0;
}
</output>This is a little bit changed code from official example of using ffmpeg called transcoding.c
I only read packets from one stream and write them to another stream. It works fine.
then I add to main a condition. If it is a packet with video frame, I will decode it, then encode and write to another stream. No other actions with frame.
My addition code below :
static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) {
int ret;
int got_frame_local;
AVPacket enc_pkt;
int(*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) = avcodec_encode_video2 ;
if (!got_frame)
got_frame = &got_frame_local;
av_log(NULL, AV_LOG_INFO, "Encoding frame\n");
/* encode filtered frame */
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = enc_func(stream_ctx[stream_index].enc_ctx, &enc_pkt,
filt_frame, got_frame);
if (ret < 0)
return ret;
if (!(*got_frame))
return 0;
/* prepare packet for muxing */
enc_pkt.stream_index = stream_index;
av_packet_rescale_ts(&enc_pkt,
stream_ctx[stream_index].enc_ctx->time_base,
ofmt_ctx->streams[stream_index]->time_base);
av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");
/* mux encoded frame */
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
return ret;
}
static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
{
int ret;
av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");
while (1) {
av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");
ret = encode_write_frame(frame, stream_index, NULL);
if (ret < 0)
break;
break;
}
return ret;
}
int main(int argc, char **argv)
{
int ret;
AVPacket packet = {0};
packet.data = NULL;
packet.size = 0 ;
AVFrame *frame = NULL;
enum AVMediaType type;
unsigned int stream_index;
unsigned int i;
int got_frame;
int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);
if (argc != 3) {
av_log(NULL, AV_LOG_ERROR, "Usage: %s <input file="file" /> <output file="file">\n", argv[0]);
return 1;
}
av_register_all();
avfilter_register_all();
if ((ret = open_input_file(argv[1])) < 0)
goto end;
if ((ret = open_output_file(argv[2])) < 0)
goto end;
/* read all packets */
while (1) {
if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)
break;
stream_index = packet.stream_index;
type = ifmt_ctx->streams[packet.stream_index]->codecpar->codec_type;
av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",
stream_index);
if (type == AVMEDIA_TYPE_VIDEO)
{
av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");
frame = av_frame_alloc();
if (!frame) {
ret = AVERROR(ENOMEM);
break;
}
av_packet_rescale_ts(&packet,
ifmt_ctx->streams[stream_index]->time_base,
stream_ctx[stream_index].dec_ctx->time_base);
dec_func = avcodec_decode_video2;
ret = dec_func(stream_ctx[stream_index].dec_ctx, frame,
&got_frame, &packet);
if (ret < 0) {
av_frame_free(&frame);
av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");
break;
}
if (got_frame) {
frame->pts = frame->best_effort_timestamp;
ret = filter_encode_write_frame(frame, stream_index);
av_frame_free(&frame);
if (ret < 0)
goto end;
}
else {
av_frame_free(&frame);
}
}
else
{
/* remux this frame without reencoding */
av_packet_rescale_ts(&packet,
ifmt_ctx->streams[stream_index]->time_base,
ofmt_ctx->streams[stream_index]->time_base);
ret = av_interleaved_write_frame(ofmt_ctx, &packet);
if (ret < 0)
goto end;
}
av_packet_unref(&packet);
}
av_write_trailer(ofmt_ctx);
end:
av_packet_unref(&packet);
av_frame_free(&frame);
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
avcodec_free_context(&stream_ctx[i].dec_ctx);
if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && stream_ctx[i].enc_ctx)
avcodec_free_context(&stream_ctx[i].enc_ctx);
}
av_free(stream_ctx);
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
return ret ? 1 : 0;
}
</output>And the result is different.
For a test I took a SampleVideo_1280x720_1mb.flv.
It hasFile size : 1.00 MiB
Overall bit rate : 1 630 kb/sAfter my decode/encode actions the result became :
File size : 1.23 MiB
Overall bit rate : 2 005 kb/sOther parameters (video bit rate, audio bit rate, etc) are the same.
What am I doing wrong ? How to control overall bit rate ? I suppose, something wrong with encoder/decoder, but what ?
UPD :
I get that when in functionopen_input_file
I writeif (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
{
codec_ctx->framerate = av_guess_frame_rate(ifmt_ctx, stream, NULL);
}I get what I get (bigger size and bit rate).
And when in this function I write
if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
{
codec_ctx = ifmt_ctx->streams[i]->codec;
}I get smaller size and bit rate.
File size : 900 KiB
Overall bit rate : 1 429 kb/sBut how to get the exactly size and frame rate as in the original file ?