我想让一个播放器可以运行webm(vp9 8/vp9 9)文件。
我制作播放器,以便每次它找到集群时,将集群发送到解码器,并将所有帧放入内存中。
奇怪的事情发生了,如果我多次调用同一个集群--译码器" vpx_codec_get_frame()“--停止查找某些帧,如果我多次重复这个过程,集群中没有解码任何帧,但是每次在我试图解码一个帧之前,我称之为"vpx_codec_decode()”,即使vpx_codec_get_frame()返回一个空指针,它也返回true;
此外,解码过程受我使用多少线程的影响,例如,如果我使用一个线程和8个线程,从集群中得到不同数量的帧。
我怀疑线程可能没有同时完成,一个新的缓冲区帧即将出现,这可能会导致问题。
另外,我在一个Mkv视频上测试我的播放器,mkv视频是通过使用mkvmerge工具合并三个视频获得的,我的播放器应该打开一个包含多个音轨的mkv文件,并同时显示所有的音轨。
下面是代码:初始化解码器:
VPXDecoder::VPXDecoder(const WebMDemuxer &demuxer, unsigned threads) :
m_ctx(NULL),
m_iter(NULL),
m_delay(0),
m_last_space(VPX_CS_UNKNOWN)
{
if (threads > 8)
threads = 8;
else if (threads < 1)
threads = 1;
const vpx_codec_dec_cfg_t codecCfg = {
threads,
0,
0
};
vpx_codec_iface_t *codecIface = NULL;
switch (demuxer.getVideoCodec())
{
case WebMDemuxer::VIDEO_VP8:
codecIface = vpx_codec_vp8_dx();
break;
case WebMDemuxer::VIDEO_VP9:
codecIface = vpx_codec_vp9_dx();
m_delay = threads - 1;
break;
default:
return;
}
m_ctx = new vpx_codec_ctx_t;
if (vpx_codec_dec_init(m_ctx, codecIface, &codecCfg, m_delay > 0 ? VPX_CODEC_USE_FRAME_THREADING : 0))
{
delete m_ctx;
m_ctx = NULL;
}
}
下面是调用vpx_codec_decode()的代码:
bool VPXDecoder::decode(const WebMFrame &frame)
{
m_iter = NULL;
this->decodead = !vpx_codec_decode(m_ctx, frame.buffer, frame.bufferSize, NULL, 0);
return decodead;
}
最后,图像应该解码的地方:
VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image)
{
IMAGE_ERROR err = NO_FRAME;
vpx_image_t *img = NULL;
img = vpx_codec_get_frame(m_ctx, &m_iter);
if (/*vpx_image_t *img = vpx_codec_get_frame(m_ctx, &m_iter)*/ img != NULL)
{
// It seems to be a common problem that UNKNOWN comes up a lot, yet FFMPEG is somehow getting accurate colour-space information.
// After checking FFMPEG code, *they're* getting colour-space information, so I'm assuming something like this is going on.
// It appears to work, at least.
if (img->cs != VPX_CS_UNKNOWN)
m_last_space = img->cs;
if ((img->fmt & VPX_IMG_FMT_PLANAR) && !(img->fmt & (VPX_IMG_FMT_HAS_ALPHA | VPX_IMG_FMT_HIGHBITDEPTH)))
{
if (img->stride[0] && img->stride[1] && img->stride[2])
{
const int uPlane = !!(img->fmt & VPX_IMG_FMT_UV_FLIP) + 1;
const int vPlane = !(img->fmt & VPX_IMG_FMT_UV_FLIP) + 1;
image.w = img->d_w;
image.h = img->d_h;
image.cs = m_last_space;
image.chromaShiftW = img->x_chroma_shift;
image.chromaShiftH = img->y_chroma_shift;
image.planes[0] = img->planes[0];
image.planes[1] = img->planes[uPlane];
image.planes[2] = img->planes[vPlane];
image.linesize[0] = img->stride[0];
image.linesize[1] = img->stride[uPlane];
image.linesize[2] = img->stride[vPlane];
err = NO_ERROR;
}
}
else
{
err = UNSUPPORTED_FRAME;
}
}
return err;
}
在我的项目中,我使用以下代码:
https://github.com/zaps166/libsimplewebm
有人能推荐另一种方法来解码vp8/9帧或者对我的代码进行罚款吗?
发布于 2020-09-09 06:29:13
我发现了这个问题,我构建了我的播放器,因为它一次只请求一个集群,但是我不知道webm文件需要在每个集群的开头有一个关键帧,所以解决方案是在每个集群的开头创建一个关键帧,然后从那里使用解码器。
https://stackoverflow.com/questions/61633861
复制相似问题