【问题标题】:ffmpeg audio frame from directshow sampleCB imediasample来自directshow sampleCB imediasample的ffmpeg音频帧
【发布时间】:2017-01-04 17:28:51
【问题描述】:

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

这是我的示例 cb 代码:

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

这是 samplegrabber pin 媒体类型:

    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 多路复用示例来处理帧,我认为我只需要更改代码的信号生成部分:

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;
}

【问题讨论】:

  • 问题没有明确定义。您需要提供有关 DirectShow 捕获的更多数据,以及尝试使用 libav 编写的代码。
  • 很简单!我想使用 directshow 抓取一个媒体样本并制作一个 avframe,我为视频帧执行此操作,但我无法为音频帧执行此操作。
  • 是的。每个人都可以提供帮助。

标签: c++ qt audio ffmpeg directshow


【解决方案1】:

代码 sn-ps 建议您使用 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 将压缩音频发送到写入。您将代码 sn-ps 附加到问题的方式让我觉得您做错了。对于初学者,您仍然没有显示相关代码,这让我认为您很难确定哪些代码是相关的。然后,您正在处理您的 AAC 数据,就好像它是 get_audio_frame 代码 sn-p 中的原始 PCM 音频一样,而您有兴趣查看 FFmpeg 示例代码,并考虑到您已经有压缩的 AAC 数据并且示例变得稀薄从avcodec_encode_audio2 电话返回后。这是您应该合并代码和示例的地方。

【讨论】:

  • 是的,我的 samplegrabber 工作正常,我可以使用 c++ 将原始数据保存到文件中并播放。没错,由于我传入的音频流,我在示例抓取器 pin 媒体类型中使用 aac_latm,现在我从您的回复中发现我必须在我的 avformatcontext 中使用 AV_CODEC_ID_AAC_LATM 编解码器,但是当我使用此编解码器时, avcodec_find_encoder(codec_id) 返回“找不到此编解码器的编码器!请帮助我。谢谢
猜你喜欢
  • 1970-01-01
  • 2018-10-29
  • 2016-02-26
  • 2018-03-16
  • 2018-01-23
  • 1970-01-01
  • 2020-07-14
  • 2011-12-23
  • 1970-01-01
相关资源
最近更新 更多