从 AVPacket 中填充 h264 视频的 CMediaType 和 IMediaSample

发布于 2024-11-29 15:37:59 字数 2094 浏览 1 评论 0原文

我已经搜索过,但几乎什么也没找到,所以我非常感谢您对我的问题提供帮助。

我正在编写一个 DirectShow 源过滤器,它使用 libav 从 youtube 的 FLV 文件读取和发送下游 h264 数据包。但我找不到合适的 libav 结构字段来正确实现过滤器的 GetMediType() 和 FillBuffer()。某些 libav 字段为空。结果,h264 解码器在尝试处理接收到的数据时崩溃。

我哪里错了?使用 libav 或 DirectShow 接口?也许 h264 在使用 libav 时需要额外的处理,或者我错误地填写了参考时间?有人有任何可用于使用 libav 编写 DirectShow h264 源过滤器的链接吗?

GetMediaType() 的一部分:

VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*) toMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
pvi->AvgTimePerFrame = UNITS_PER_SECOND / m_pFormatContext->streams[m_streamNo]->codec->sample_rate; //sample_rate is 0
pvi->dwBitRate       = m_pFormatContext->bit_rate;
pvi->rcSource        = videoRect;
pvi->rcTarget        = videoRect;

//Bitmap
pvi->bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth    = videoRect.right;
pvi->bmiHeader.biHeight   = videoRect.bottom;
pvi->bmiHeader.biPlanes   = 1;
pvi->bmiHeader.biBitCount = m_pFormatContext->streams[m_streamNo]->codec->bits_per_raw_sample;//or should here be bits_per_coded_sample
pvi->bmiHeader.biCompression = FOURCC_H264;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);

FillBuffer() 的一部分:

//Get buffer pointer
BYTE* pBuffer = NULL;
if (pSamp->GetPointer(&pBuffer) < 0)
   return S_FALSE;

//Get next packet
AVPacket* pPacket = m_mediaFile.getNextPacket();
if (pPacket->data == NULL)
   return S_FALSE;

//Check packet and buffer size
if (pSamp->GetSize() < pPacket->size)
   return S_FALSE;

//Copy from packet to sample buffer
memcpy(pBuffer, pPacket->data, pPacket->size);

//Set media sample time
REFERENCE_TIME start    = m_mediaFile.timeStampToReferenceTime(pPacket->pts);
REFERENCE_TIME duration = m_mediaFile.timeStampToReferenceTime(pPacket->duration);
REFERENCE_TIME end      = start + duration;
pSamp->SetTime(&start, &end);
pSamp->SetMediaTime(&start, &end);

PS 我已经使用 hax264 解码器调试了我的过滤器,它在调用 libav 已弃用的函数 img_convert() 时崩溃。

I have searched and have found almost nothing, so I would really appreciate some help with my question.

I am writting a DirectShow source filter which uses libav to read and send downstream h264 packets from youtube's FLV file. But I can't find appropriate libav structure's fields to implement correctly filter's GetMediType() and FillBuffer(). Some libav fields is null. In consequence h264 decoder crashes in attempt to process received data.

Where am I wrong? In working with libav or with DirectShow interfaces? Maybe h264 requires additional processing when working with libav or I fill reference time incorrectly? Does someone have any links useful for writing DirectShow h264 source filter with libav?

Part of GetMediaType():

VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER*) toMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
pvi->AvgTimePerFrame = UNITS_PER_SECOND / m_pFormatContext->streams[m_streamNo]->codec->sample_rate; //sample_rate is 0
pvi->dwBitRate       = m_pFormatContext->bit_rate;
pvi->rcSource        = videoRect;
pvi->rcTarget        = videoRect;

//Bitmap
pvi->bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth    = videoRect.right;
pvi->bmiHeader.biHeight   = videoRect.bottom;
pvi->bmiHeader.biPlanes   = 1;
pvi->bmiHeader.biBitCount = m_pFormatContext->streams[m_streamNo]->codec->bits_per_raw_sample;//or should here be bits_per_coded_sample
pvi->bmiHeader.biCompression = FOURCC_H264;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);

Part of FillBuffer():

//Get buffer pointer
BYTE* pBuffer = NULL;
if (pSamp->GetPointer(&pBuffer) < 0)
   return S_FALSE;

//Get next packet
AVPacket* pPacket = m_mediaFile.getNextPacket();
if (pPacket->data == NULL)
   return S_FALSE;

//Check packet and buffer size
if (pSamp->GetSize() < pPacket->size)
   return S_FALSE;

//Copy from packet to sample buffer
memcpy(pBuffer, pPacket->data, pPacket->size);

//Set media sample time
REFERENCE_TIME start    = m_mediaFile.timeStampToReferenceTime(pPacket->pts);
REFERENCE_TIME duration = m_mediaFile.timeStampToReferenceTime(pPacket->duration);
REFERENCE_TIME end      = start + duration;
pSamp->SetTime(&start, &end);
pSamp->SetMediaTime(&start, &end);

P.S. I've debugged my filter with hax264 decoder and it crashes on call to libav deprecated function img_convert().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凡尘雨 2024-12-06 15:37:59

以下是构建正确的 H.264 媒体类型所需的 MSDN 链接:H.264 视频类型

Here is the MSDN link you need to build a correct H.264 media type: H.264 Video Types

旧梦荧光笔 2024-12-06 15:37:59

您必须使用正确的值填写正确的字段。

AM_MEDIA_TYPE 应包含适用于 h264 的正确 MEDIASUBTYPE。

这些都是完全错误的:

pvi->bmiHeader.biWidth = videoRect.right;

pvi->bmiHeader.biHeight = videoRect.bottom;

您应该使用独立于 rcSource/rcTarget 的宽度/高度,因为它们是指示器,如果您从其他过滤器获取它们,则可能完全为零。

pvi->bmiHeader.biBitCount = m_pFormatContext->streams[m_streamNo]->codec->bits_per_raw_sample;//或者这里应该是bits_per_coded_sample

仅当 biWidth*biHeight*biBitCount/8 是样本的真实大小时,这才有意义。我不这么认为......

pvi->bmiHeader.biCompression = FOURCC_H264;

这也必须在子类型参数的 AM_MEDIA_TYPE 中传递。

pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);

这会失败,因为 fourcc 对于该函数来说是未知的,并且由于不是完整帧,因此该示例的位数明显错误。

你必须看看下游的 h264 过滤器是如何处理数据流的。这似乎是有缺陷的。

You have to fill the right fields with the right values.

The AM_MEDIA_TYPE should contain the right MEDIASUBTYPE for h264.

And these are plain wrong :

pvi->bmiHeader.biWidth = videoRect.right;

pvi->bmiHeader.biHeight = videoRect.bottom;

You should use a width/height which is independent of the rcSource/rcTarget, due to the them being indicators, and maybe completely zero if you take them from some other filter.

pvi->bmiHeader.biBitCount = m_pFormatContext->streams[m_streamNo]->codec->bits_per_raw_sample;//or should here be bits_per_coded_sample

This only makes sense if biWidth*biHeight*biBitCount/8 are the true size of the sample. I do not think so ...

pvi->bmiHeader.biCompression = FOURCC_H264;

This must also be passed in the AM_MEDIA_TYPE in the subtype parameter.

pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);

This fails, because the fourcc is unknown to the function and the bitcount is plain wrong for this sample, due to not being a full frame.

You have to take a look at how the data stream is handled by the downstream h264 filter. This seems to be flawed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文