2
votes

I encoded some frames into a MP4 using FFmpeg API, but the MP4 could't be played in the Windows Media Player.

By comparison with the normal MP4 using ffprobe, I found that the FOURCC of the problematic MP4 is 'H264' while the normal MP4 is 'AVC1'. According to H.264 Video Types, 'AVC1' has start codes but 'H264' hasn't.I also learned that we shoud manually add sps and pps before H.264 stream when demuxing a MP4.

Now I don't know how to add start code or sps/pps to my MP4, please give me a hand. How I should do to generate a MP4 which can be played in the Windows Media Player?

I have tried to add h264 bitstream filter but it didn't work. The code below:

 AVBitStreamFilterContext *bsfc = NULL;
bsfc = av_bitstream_filter_init("h264_mp4toannexb");
if (bsfc == NULL) {
            printf("bsfc is NULL\n");
}
        
av_bitstream_filter_filter(bsfc, codec_ctx, NULL, &(pkt->data), &(pkt->size), pkt->data, pkt->size, 0);

av_bitstream_filter_close(bsfc);

After a lot of trying, I found that manually adding sps and pps to codec_ctx->extradata effective:

unsigned char sps_pps[23] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x29, 0xac, 0x1b, 0x1a, 0x12, 0xe0, 0x51, 0x90,
                              0x00, 0x00, 0x00, 0x01, 0x68, 0xea, 0x43, 0xcb };
codec_ctx->extradata_size = 23;
codec_ctx->extradata = (uint8_t*)av_malloc(23 + AV_INPUT_BUFFER_PADDING_SIZE);
if (codec_ctx->extradata == NULL) {
    printf("could not av_malloc the video params extradata!\n");
    ERR_NULL_EXIT
    }
memcpy(codec_ctx->extradata, sps_pps, 23);

The code above refered to an answer of @szatmary

Now generated MP4 can be played in Windows Media Player. But a new question emerges because I don't konw what correct value of sps/pps is. It cause that the width and height of frame presented in the Windows Explorer is incorrect. So I need to set the correct sps/pps. I also read the document of sps/pps but get confused because some parameters have variable bits. So can anybody tell me how to set the sps/pps correctly?

2

2 Answers

4
votes

I finally found the fundamental solution to the problem is that to add a line of code before the call of avcodec_open2.

codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

The encoder would set the sps/pps in the avcodec_open2() function if you set the codec_ctx->flags.

And you can refer to below sites if you want to know more about sps/pps.

Possible Locations for Sequence/Picture Parameter Set(s) for H.264 Stream

0
votes

manually adding sps and pps to codec_ctx->extradata

This works for me.

how to set the sps/pps correctly?

I remux the video with FFmpeg command line, then use mp4info to read pps/sps from the remuxed video.