2

I'm trying to convert an mp4 file to mpegts using libav. The code works, but outputs a file that can not be played by any player.

Here is the input file (it is video only, no audio)

here is the code I have so far:

int convert(const char *input, const char *output)
{
AVFormatContext *inputContext = NULL;
AVFormatContext *outputContext = NULL;
AVCodecContext *input_codec_context = NULL;
AVCodecContext *output_codec_context = NULL;
AVCodec *output_codec = NULL;
AVCodec *input_codec = NULL;
AVStream *stream = NULL;
AVIOContext *avioContext = NULL;

av_register_all();
avformat_network_init();
avformat_alloc_output_context2(&outputContext, NULL, "mpegts", output);
avio_open(&avioContext, output, AVIO_FLAG_WRITE);
outputContext->pb = avioContext;
stream = avformat_new_stream(outputContext, output_codec);

avformat_open_input(&inputContext, input, NULL, NULL);

input_codec_context = inputContext->streams[0]->codec;
input_codec = avcodec_find_decoder(inputContext->streams[0]->codec->codec_id);
avcodec_open2(inputContext->streams[0]->codec, input_codec, NULL);
avformat_find_stream_info(inputContext, NULL);
outputContext->oformat = av_guess_format(NULL, output, NULL);
output_codec = input_codec;

output_codec_context = avcodec_alloc_context3(NULL);
avcodec_copy_context(output_codec_context, input_codec_context);

avcodec_open2(output_codec_context, output_codec, NULL);

AVPacket packet;
av_init_packet(&packet);

avformat_write_header(outputContext, NULL);
while (!av_read_frame(inputContext, &packet)) {

    av_write_frame(outputContext, &packet);
}
av_free_packet(&packet);

av_write_trailer(outputContext);
avformat_close_input(&inputContext);
avformat_free_context(inputContext);
avformat_free_context(outputContext);

return 0;
}

any help appreciated.

1 Answer 1

5
+100

mp4 and mpegts assume a different bitstream format for h264.

You need to insert h264_mp4toannexb to reformat the AVPacket you are getting.

To allocate the context

    AVBitStreamFilterContext *bsf = av_bitstream_filter_init("h264_mp4toannexb");

in your demux loop

    AVPacket new_pkt = *pkt;
    int ret = av_bitstream_filter_filter(bsfc, avctx, NULL,
                                         &new_pkt.data, &new_pkt.size,
                                         pkt->data, pkt->size,
                                         pkt->flags & AV_PKT_FLAG_KEY);
    if (ret > 0) {
        // non-zero positive, you have new memory allocated, 
        // keep it referenced in the AVBuffer
        av_free_packet(pkt);
        new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size,
                                       av_buffer_default_free, NULL, 0);
        // handle memory error here

    } else if (ret < 0) {
        // handle failure here

    }
    // ret == 0, no problems, nothing else to do
    *pkt = new_pkt;
Sign up to request clarification or add additional context in comments.

5 Comments

The equivalent: avconv -i in.mp4 -bsf:v h264mp4toannexb -c copy out.ts
the code above didn't solve it, the avconv did work though. I guess there is something else wrong with my code.
One of the other problems is where you allocate the AVStream I guess.
AVStream was the issue indeed. It's working now. Thanks. I will post the code I ended up with in a couple of days.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.