最近在研究用Emscripten开发JavaScript的直播播放器,使用ffmpeg内置的h264解码速度还是可以接受的,本想使用openh264的解码进行比较,但发现非常慢,无法达到640×480@30帧的解码速度。
本来以前也有过用openh264的项目,直接使用libopenh264进行解码速度还是很快的。但编译进ffmpeg里使用就特别慢,于是-g重新编译NodePlayer.js并开始Chrome Performance录制。
libopenh264dec.c ->svc_decode_frame中,av_image_copy居然比DecodeFrame2解码耗时还多。这段代码是这样的
static int svc_decode_frame(AVCodecContext *avctx, void *data,
int *got_frame, AVPacket *avpkt)
{
SVCContext *s = avctx->priv_data;
SBufferInfo info = { 0 };
uint8_t* ptrs[3];
int ret, linesize[3];
AVFrame *avframe = data;
DECODING_STATE state;
state = (*s->decoder)->DecodeFrame2(s->decoder, avpkt->data, avpkt->size, ptrs, &info);
if (state != dsErrorFree) {
av_log(avctx, AV_LOG_ERROR, "DecodeFrame2 failed\n");
return AVERROR_UNKNOWN;
}
if (info.iBufferStatus != 1) {
av_log(avctx, AV_LOG_DEBUG, "No frame produced\n");
return avpkt->size;
}
ret = ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight);
if (ret < 0)
return ret;
// The decoder doesn't (currently) support decoding into a user
// provided buffer, so do a copy instead.
if (ff_get_buffer(avctx, avframe, 0) < 0) { av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n"); return AVERROR(ENOMEM); } linesize[0] = info.UsrData.sSystemBuffer.iStride[0]; linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1]; av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height);
avframe->pts = avpkt->pts;
avframe->pkt_dts = avpkt->dts;
#if FF_API_PKT_PTS
FF_DISABLE_DEPRECATION_WARNINGS
avframe->pkt_pts = avpkt->pts;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
*got_frame = 1;
return avpkt->size;
}
原来openh264的实现里面DecodeFrame2需要传入的只是 uint8_t* ptrs[3]; 指针,解码器内部分配内存,这导致不能直接解码到我们预先分配好内存的AVFrame->data上去,解码后还有进行内存拷贝,速度自然就快不起来了。
原创文章,转载请注明: 转载自贝壳博客
本文链接地址: ffmpeg.js使用libopenh264解码性能低的原因