ffmpeg支持G711音频和H.264视频数据同步封装进MP4文件

1、编译参数 
在使用./configure编译ffmpeg库时,需要添加一些编译选项支持项目所需要的功能。具体参数如下:

--enable-encoder=pcm_alaw --enable-decoder=pcm_alaw //支持PCM和G711编解码
--enable-demuxer=mov  //支持mov,mp4,m4a,3gp,3g2,mj2解复用

2、代码模块 
ffmpeg本身是支持H264+AAC的mp4封装格式的,但是并不支持H264+G711的mp4封装格式。 
ffmpeg中对MP4的打包处理是在movenc.c中,为了能够使ffmpeg支持H264+G711的mp4封装格式,同时也可以支持音频原始数据封装,修改libavformat/movenc.c代码以下部分:

if (version == 2) {
        avio_wb16(pb, 3);
        avio_wb16(pb, 16);
        avio_wb16(pb, 0xfffe);
        avio_wb16(pb, 0);
        avio_wb32(pb, 0x00010000);
        avio_wb32(pb, 72);
        avio_wb64(pb, av_double2int(track->enc->sample_rate));
        avio_wb32(pb, track->enc->channels);
        avio_wb32(pb, 0x7F000000);
        avio_wb32(pb, av_get_bits_per_sample(track->enc->codec_id));
        avio_wb32(pb, mov_get_lpcm_flags(track->enc->codec_id));
        avio_wb32(pb, track->sample_size);
        avio_wb32(pb, get_samples_per_packet(track));
    } else {
        if (track->mode == MODE_MOV) {
            avio_wb16(pb, track->enc->channels);
            if (track->enc->codec_id == AV_CODEC_ID_PCM_U8 ||
                track->enc->codec_id == AV_CODEC_ID_PCM_S8)
                avio_wb16(pb, 8); /* bits per sample */
            else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_G726)
                avio_wb16(pb, track->enc->bits_per_coded_sample);
            else
                avio_wb16(pb, 16);
            avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
        } else { /* reserved for mp4/3gp */
            avio_wb16(pb, track->enc->channels > 0 ? 
                          track->enc->channels : 1);
            track->enc->bits_per_coded_sample = av_get_bits_per_sample(track->enc->codec_id);
            avio_wb16(pb, track->enc->bits_per_coded_sample > 0 ? 
                          track->enc->bits_per_coded_sample : 16);
            avio_wb16(pb, 0);
        }

        avio_wb16(pb, 0); /* packet size (= 0) */
        avio_wb16(pb, track->enc->sample_rate <= UINT16_MAX ?
                      track->enc->sample_rate : 0);
        avio_wb16(pb, 0); /* Reserved */
    }
static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
{
    int tag;

    if (track->mode == MODE_MP4 || track->mode == MODE_PSP)
        tag = mp4_get_codec_tag(s, track);
    else if (track->mode == MODE_ISM) {
        tag = mp4_get_codec_tag(s, track);
        if (!tag && track->enc->codec_id == AV_CODEC_ID_WMAPRO)
            tag = MKTAG('w', 'm', 'a', ' ');
    } else if (track->mode == MODE_IPOD)
        tag = ipod_get_codec_tag(s, track);
    else if (track->mode & MODE_3GP)
        tag = ff_codec_get_tag(codec_3gp_tags, track->enc->codec_id);
    else if (track->mode == MODE_F4V)
        tag = ff_codec_get_tag(codec_f4v_tags, track->enc->codec_id);

    if (tag == 0){
        tag = mov_get_codec_tag(s, track);
    }
    return tag;
}


--------------------- 
作者:珠雨妮儿 
来源:CSDN 
原文:https://blog.csdn.net/zhuyunier/article/details/80814227 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要使用 DirectShow 采集音视频数据,并使用 x264 和 LAME 行编码。然后,你需要使用 FFmpeg 封装视频数据MP4 文件。下面是一个简单的示例代码,展示如何实现音视频同步: ```c++ // 初始化 DirectShow 采集器 CoInitialize(NULL); IGraphBuilder* pGraph = NULL; IMediaControl* pControl = NULL; ICaptureGraphBuilder2* pBuilder = NULL; IBaseFilter* pAudioCaptureFilter = NULL; IBaseFilter* pVideoCaptureFilter = NULL; IBaseFilter* pAudioEncoderFilter = NULL; IBaseFilter* pVideoEncoderFilter = NULL; IBaseFilter* pMuxFilter = NULL; CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuilder); pBuilder->SetFiltergraph(pGraph); // 添加音频采集器和编码器 CoCreateInstance(CLSID_AudioCapture, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pAudioCaptureFilter); CoCreateInstance(CLSID_AudioEncoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pAudioEncoderFilter); pGraph->AddFilter(pAudioCaptureFilter, L"Audio Capture Filter"); pGraph->AddFilter(pAudioEncoderFilter, L"Audio Encoder Filter"); // 添加视频采集器和编码器 CoCreateInstance(CLSID_VideoCapture, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideoCaptureFilter); CoCreateInstance(CLSID_VideoEncoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideoEncoderFilter); pGraph->AddFilter(pVideoCaptureFilter, L"Video Capture Filter"); pGraph->AddFilter(pVideoEncoderFilter, L"Video Encoder Filter"); // 添加 MP4 封装器 CoCreateInstance(CLSID_MPEG4Muxer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMuxFilter); pGraph->AddFilter(pMuxFilter, L"MP4 Mux Filter"); // 连接音频采集器和编码器 IPin* pAudioCaptureOutPin = GetPin(pAudioCaptureFilter, PINDIR_OUTPUT); IPin* pAudioEncoderInPin = GetPin(pAudioEncoderFilter, PINDIR_INPUT); pGraph->Connect(pAudioCaptureOutPin, pAudioEncoderInPin); // 连接视频采集器和编码器 IPin* pVideoCaptureOutPin = GetPin(pVideoCaptureFilter, PINDIR_OUTPUT); IPin* pVideoEncoderInPin = GetPin(pVideoEncoderFilter, PINDIR_INPUT); pGraph->Connect(pVideoCaptureOutPin, pVideoEncoderInPin); // 连接音频编码器和 MP4 封装器 IPin* pAudioEncoderOutPin = GetPin(pAudioEncoderFilter, PINDIR_OUTPUT); IPin* pMuxInAudioPin = GetPin(pMuxFilter, PINDIR_INPUT, MEDIATYPE_Audio); pGraph->Connect(pAudioEncoderOutPin, pMuxInAudioPin); // 连接视频编码器和 MP4 封装器 IPin* pVideoEncoderOutPin = GetPin(pVideoEncoderFilter, PINDIR_OUTPUT); IPin* pMuxInVideoPin = GetPin(pMuxFilter, PINDIR_INPUT, MEDIATYPE_Video); pGraph->Connect(pVideoEncoderOutPin, pMuxInVideoPin); // 开始采集和编码 pControl->Run(); // 等待直到采集结束 while (true) { if (CheckCaptureEnded(pAudioCaptureFilter) && CheckCaptureEnded(pVideoCaptureFilter)) { break; } Sleep(10); } // 停止采集和编码 pControl->Stop(); // 释放资源 pMuxFilter->Release(); pVideoEncoderFilter->Release(); pVideoCaptureFilter->Release(); pAudioEncoderFilter->Release(); pAudioCaptureFilter->Release(); pBuilder->Release(); pControl->Release(); pGraph->Release(); CoUninitialize(); ``` 在上面的代码,我们使用 DirectShow 采集音频视频数据,并将它们分别传递给音频视频编码器行编码。然后,我们将编码后的音频视频数据传递给 MP4 封装器,将它们封装MP4 文件。在这个过程,我们需要确保音频视频数据的时间戳是同步的,以确保最终的 MP4 文件的音视频同步的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值