来自directshow sampleCB imediasample的ffmpeg音频帧

时间:2016-08-28 16:31:38

标签: c++ qt audio ffmpeg directshow

我使用isamplegrabber sampleCB回调来获取音频样本,我可以从imediasample获得缓冲区和缓冲区长度,我使用avcodec_fill_audio_frame(frame,ost-> enc-> channels,ost-> enc-> sample_fmt,( uint8_t *)buffer,length,0)来制作一个avframe,但是这个帧不会在我的mux文件中发出任何音频!我认为长度比frame_size小很多。 每个人都能帮帮我吗?或者如果可能的话给我一些例子。 谢谢

这是我的samplecb代码:

     HRESULT AudioSampleGrabberCallBack::SampleCB(double Time, IMediaSample*pSample){   
        BYTE *pBuffer;
        pSample->GetPointer(&pBuffer);
        long BufferLen = pSample->GetActualDataLength();        
        muxer->PutAudioFrame(pBuffer,BufferLen);    
}

这是samplegrabber pin media type:

    AM_MEDIA_TYPE pmt2;
    ZeroMemory(&pmt2, sizeof(AM_MEDIA_TYPE));
    pmt2.majortype = MEDIATYPE_Audio;
    pmt2.subtype = FOURCCMap(0x1602);
    pmt2.formattype = FORMAT_WaveFormatEx;
    hr = pSampleGrabber_audio->SetMediaType(&pmt2);

之后我使用ffmpeg muxing示例来处理帧,我想我只需要更改信号生成部分代码:

AVFrame *Muxing::get_audio_frame(OutputStream *ost,BYTE* buffer,long length)
{
    AVFrame *frame = ost->tmp_frame;
    int j, i, v;
    uint16_t *q = (uint16_t*)frame->data[0];

    int buffer_size = av_samples_get_buffer_size(NULL, ost->enc->channels,
                                                 ost->enc->frame_size,
                                                 ost->enc->sample_fmt, 0);
//    uint8_t *sample = (uint8_t *) av_malloc(buffer_size);
    av_samples_alloc(&frame->data[0], frame->linesize, ost->enc->channels, ost->enc->frame_size, ost->enc->sample_fmt, 1);
    avcodec_fill_audio_frame(frame, ost->enc->channels, ost->enc->sample_fmt,frame->data[0], buffer_size, 1);

    frame->pts = ost->next_pts;
    ost->next_pts  += frame->nb_samples;

    return frame;
}

1 个答案:

答案 0 :(得分:1)

代码片段建议您使用Sample Grabber获取AAC数据,并且您正尝试使用FFmpeg的libavformat将其写入文件。这可以解决。

您初始化样本抓取器以获取WAVE_FORMAT_AAC_LATM格式的音频数据。这种格式不是那么广泛,您有兴趣查看过滤器图表,以确保Sample Grabber上的上游连接符合您的预期。有可能在某种程度上有一个奇怪的过滤器链假装产生AAC-LATM,现实是数据无效(或甚至没有达到抓取器回调)。因此,您需要查看过滤器图表(请参阅Loading a Graph From an External ProcessUnderstanding Your DirectShow Filter Graph),然后使用调试器逐步调试回调,以确保获取数据并且有意义。

接下来,您需要初始化AVFormatContextAVStream以表明您将以AAC LATM格式编写数据。提供的代码并未显示您正在正确执行。 sample you are referring to正在使用默认编解码器。

然后,您需要确保传入数据和FFmpeg输出设置是否同意数据是否具有ADTS标头,提供的代码不会对此有所了解。

此外,我担心您可能会错误地准备音频数据。相关示例生成原始音频数据并应用编码器以使用avcodec_encode_audio2生成压缩内容。然后使用av_interleaved_write_frame将压缩音频打包发送到写入。你将代码片段附加到问题的方式让我觉得你做错了。对于初学者,您仍然没有显示相关代码,这使我认为您无法确定哪些代码完全相关。然后,您正在处理您的AAC数据,就好像它是get_audio_frame代码段中的原始PCM音频,而您有兴趣查看FFmpeg示例代码时考虑到您已经有压缩的AAC数据并且样本到达了点从avcodec_encode_audio2电话回来后。这是您应该合并代码和示例的地方。