最近在研究用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解码耗时还多。这段代码是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
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解码性能低的原因