5

I am developing a tool which receives a h.264 live stream from the network (the sender is a hardware encoder), buffers the last x-minutes and creates a video file of the last x-minutes if triggered.

My tool is able to receive the live stream and also to buffer AVPackets the with boost::serialization. Furthermore I am able to load the buffered AVPackets.

But when I try to create/mux a video file (mp4) with the loaded AVPackets there occurs an error in the mp4-file or mp4-header. I am able to create a mp4-file and also to write Packets to the file with av_interleaved_write_frame(). The mp4-file has also a plausible size. So it seams that the AVPackets were written to the file.

But when I try to open the mp4-file with a player like vlc, the video doesn't play. The player provides an error like: the header isn't correct and doesn't play any frame. But I write the header with the writeHeader() function to the AVFormatContext.

I guess that the reason is that the AVFormatContext isn't correctly initialized but with the example of ffmpeg/libav (muxing-examples) I can't solve the problem.

Has any one a solution (example code) or an other example how to correctly initialize the AVFormatContext?

Thanks for your help. Olgen

    avcodec_init();
    avcodec_register_all();
    av_register_all();
    av_log_set_level(AV_LOG_DEBUG);

    char *outputFilename = "/tmp/output.mp4";

    // define AVOutputFormat
    AVOutputFormat *outputFormat = NULL;
    outputFormat = av_guess_format("mp4", NULL, NULL);
    if (!outputFormat) {
        fprintf(stderr, "Could not find suitable output format\n");
        return 1;
    }

    // define AVFormatContext
    AVFormatContext *formatContext = NULL;
    // lallocate the output media context
    std::cout << "alloc" << std::endl;
    formatContext = avformat_alloc_context();
//  avformat_alloc_output_context(&formatContext, outputFormat, NULL, NULL);
    if (!formatContext) {
        fprintf(stderr, "Memory error\n");
        return 1;
    }
    std::cout << "stream" << std::endl;
    AVStream * video_st = av_new_stream(formatContext, 0);
    AVCodec * codec = NULL;
    avcodec_get_context_defaults3(video_st->codec, codec);
    video_st->codec->coder_type = AVMEDIA_TYPE_VIDEO;

    video_st->codec->flags = fc->streams[0]->codec->flags;
    video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;
    video_st->disposition = fc->streams[0]->disposition;
    video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
    video_st->codec->bits_per_raw_sample = fc->streams[0]->codec->bits_per_raw_sample;
    video_st->codec->chroma_sample_location = fc->streams[0]->codec->chroma_sample_location;
    video_st->codec->codec_id = fc->streams[0]->codec->codec_id;
    video_st->codec->codec_tag = fc->streams[0]->codec->codec_tag;
    video_st->codec->time_base = fc->streams[0]->codec->time_base;
    video_st->codec->extradata = fc->streams[0]->codec->extradata;
    video_st->codec->extradata_size = fc->streams[0]->codec->extradata_size;
    video_st->codec->pix_fmt = fc->streams[0]->codec->pix_fmt;
    video_st->codec->width = fc->streams[0]->codec->width;
    video_st->codec->height = fc->streams[0]->codec->height;
    video_st->codec->sample_aspect_ratio = fc->streams[0]->codec->sample_aspect_ratio;


    std::cout << "file" << std::endl;
    avio_open(&formatContext->pb, outputFilename, AVIO_FLAG_WRITE);
    std::cout << "header" << std::endl;
    avformat_write_header(formatContext, NULL);
//  av_write_header(formatContext);

// loop to write AVPackets with av_write_frame

The programm crashes after the avformat_write_header(formatContext, NULL) with a memory error. I also tried avformat_alloc_output_context() instead of avformat_alloc_output_context2() but both functions don't work. So I used avformat_alloc_context() (see above)

I think there is an alloction problem but why I can't use avformat_alloc_output_context2 or avformat_alloc_output_context. Could somebody figure out my problem here?

Olgen2013
  • 51
  • 1
  • 1
  • 5
  • avformat_alloc_output_context[2] must be contained in the "libavformat/avformat.h". Check the ffmpeg version (see "libavformat/version.h" `LIBAVFORMAT_VERSION_MAJOR` and `LIBAVFORMAT_VERSION_MINOR`) – pogorskiy Nov 08 '13 at 11:16
  • this is my current version: `#define LIBAVFORMAT_VERSION_MAJOR 53 #define LIBAVFORMAT_VERSION_MINOR 21 #define LIBAVFORMAT_VERSION_MICRO 1` – Olgen2013 Nov 08 '13 at 11:44
  • But the file "/usr/include/libavformat/avformat.h" doesn't include either avformat_alloc_output_context2 or avformat_alloc_output_context. There is just avformat_alloc_context. What is wrong with my lib version? – Olgen2013 Nov 08 '13 at 16:49
  • I'm using av_guess_format() for guessing mp3 file format. but getting error [aac @ 0x6db9e0] Prediction is not allowed in AAC-LC. – patrick Jun 12 '15 at 06:07
  • hey have you got the solution then please share thanks in advance – Jatin Dave Apr 06 '16 at 10:26

2 Answers2

3

This is a general scheme shows how to mux video file from an existing packets

AVOutputFormat * outFmt = av_guess_format("mp4", NULL, NULL);
AVFormatContext *outFmtCtx = NULL;
avformat_alloc_output_context2(&outFmtCtx, outFmt, NULL, NULL);
AVStream * outStrm = av_new_stream(outFmtCtx, 0);

AVCodec * codec = NULL;
avcodec_get_context_defaults3(outStrm->codec, codec);
outStrm->codec->coder_type = AVMEDIA_TYPE_VIDEO;

///....
/// set some required value, such as
/// outStrm->codec->flags
/// outStrm->codec->sample_aspect_ratio
/// outStrm->disposition
/// outStrm->codec->codec_tag
/// outStrm->codec->bits_per_raw_sample
/// outStrm->codec->chroma_sample_location
/// outStrm->codec->codec_id
/// outStrm->codec->codec_tag
/// outStrm->codec->time_base
/// outStrm->codec->extradata 
/// outStrm->codec->extradata_size
/// outStrm->codec->pix_fmt
/// outStrm->codec->width
/// outStrm->codec->height
/// outStrm->codec->sample_aspect_ratio
/// see ffmpeg.c for details  

avio_open(&outFmtCtx->pb, outputFileName, AVIO_FLAG_WRITE);

avformat_write_header(outFmtCtx, NULL);

for (...)
{
av_write_frame(outFmtCtx, &pkt);
}

av_write_trailer(outFmtCtx);
avio_close(outFmtCtx->pb);
avformat_free_context(outFmtCtx);

For troubleshooting, it is useful to set detailed logging: av_log_set_level(AV_LOG_DEBUG);

pogorskiy
  • 4,705
  • 1
  • 22
  • 21
  • Thanks a lot for you answer! But the problem is that I am not able to use avformat_alloc_output_context2(). There occurs an error which say that this funktion isn't available. So I use avformat_alloc_context. I work on ubuntu 12.04 and installed ffmpeg via apt-get install. So isn't this ffmpeg version correct? – Olgen2013 Oct 30 '13 at 13:01
  • You have to use the `avformat_alloc_output_context` in your ffmpeg version. – pogorskiy Oct 30 '13 at 17:00
  • I will try to fix my problems with your tips. But soonest next week! I will report here about my progress. Thanks again für your help! – Olgen2013 Oct 30 '13 at 20:03
  • Hi! I tried to fix the porblem but I am getting a memory error. Please have a look at the provided source code above! Thnaks! Is there a version problem of ffmpeg/libav ?? – Olgen2013 Nov 08 '13 at 10:33
  • My current version: avconv -version avconv version 0.8.8-4:0.8.8-0ubuntu0.12.04.1, Copyright (c) 2000-2013 the Libav developers built on Oct 22 2013 12:35:42 with gcc 4.6.3 avconv 0.8.8-4:0.8.8-0ubuntu0.12.04.1 libavutil 51. 22. 1 / 51. 22. 1 libavcodec 53. 35. 0 / 53. 35. 0 libavformat 53. 21. 1 / 53. 21. 1 libavdevice 53. 2. 0 / 53. 2. 0 libavfilter 2. 15. 0 / 2. 15. 0 libswscale 2. 1. 0 / 2. 1. 0 libpostproc 52. 0. 0 / 52. 0. 0 – Olgen2013 Nov 08 '13 at 11:20
  • I use ffmpeg (not libav), current major version of the libavformat is 55. – pogorskiy Nov 08 '13 at 12:18
  • So I think there is my problem ... so I should uninstall libav? and which is the best way to get the same ffmpeg version as yours? ... sorry but it's my first time using ffmpeg and for a beginner it is very complex ... – Olgen2013 Nov 08 '13 at 17:22
  • I never used the libav library. Using Linux, I recommend to build the ffmpeg library from the source. The latest version can be found for example here: http://ffmpeg.zeranoe.com/builds/source/ffmpeg/ffmpeg-2.1.tar.xz. – pogorskiy Nov 08 '13 at 21:39
  • OK! Thanks! This week I will try to build ffmpeg from source and to solve the problem this way. I will report about my progress here. – Olgen2013 Nov 11 '13 at 08:11
1

This might not be the case, but avformat_write_header function should be used for writing header instead of function pointer in AVOutputFormat.write_header

Anton
  • 978
  • 5
  • 11