diff options
author | Pascal Massimino <pascal.massimino@gmail.com> | 2013-03-01 02:14:46 +0400 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-03-01 02:29:53 +0400 |
commit | 3c3a8c14897978240ad6ab7762547878d5fb24cd (patch) | |
tree | c7a2f3a6e67d29881d61968cb14a3f499f6fe102 /libavcodec/libvpxenc.c | |
parent | b56e029bdc9a68ed9decc7d3ad77e15aa5f4071d (diff) |
libvpxenc: add psnr support
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/libvpxenc.c')
-rw-r--r-- | libavcodec/libvpxenc.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 04ea031e55..bbd566d60c 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -48,6 +48,9 @@ struct FrameListData { unsigned long duration; /**< duration to show frame (in timebase units) */ uint32_t flags; /**< flags for this frame */ + uint64_t sse[4]; + int have_sse; /**< true if we have pending sse[] */ + uint64_t frame_number; struct FrameListData *next; }; @@ -57,6 +60,9 @@ typedef struct VP8EncoderContext { struct vpx_image rawimg; struct vpx_fixed_buf twopass_stats; int deadline; //i.e., RT/GOOD/BEST + uint64_t sse[4]; + int have_sse; /**< true if we have pending sse[] */ + uint64_t frame_number; struct FrameListData *coded_frame_list; int cpu_used; @@ -232,6 +238,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, { VP8Context *ctx = avctx->priv_data; struct vpx_codec_enc_cfg enccfg; + vpx_codec_flags_t flags = (avctx->flags & CODEC_FLAG_PSNR) ? VPX_CODEC_USE_PSNR : 0; int res; av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); @@ -364,7 +371,7 @@ static av_cold int vpx_init(AVCodecContext *avctx, dump_enc_cfg(avctx, &enccfg); /* Construct Encoder Context */ - res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, 0); + res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, flags); if (res != VPX_CODEC_OK) { log_encoder_error(avctx, "Failed to initialize encoder"); return AVERROR(EINVAL); @@ -397,6 +404,9 @@ static av_cold int vpx_init(AVCodecContext *avctx, vpx_img_wrap(&ctx->rawimg, VPX_IMG_FMT_I420, avctx->width, avctx->height, 1, (unsigned char*)1); + ctx->have_sse = 0; + ctx->frame_number = 0; + avctx->coded_frame = avcodec_alloc_frame(); if (!avctx->coded_frame) { av_log(avctx, AV_LOG_ERROR, "Error allocating coded frame\n"); @@ -407,13 +417,30 @@ static av_cold int vpx_init(AVCodecContext *avctx, } static inline void cx_pktcpy(struct FrameListData *dst, - const struct vpx_codec_cx_pkt *src) + const struct vpx_codec_cx_pkt *src, + VP8Context *ctx) { dst->pts = src->data.frame.pts; dst->duration = src->data.frame.duration; dst->flags = src->data.frame.flags; dst->sz = src->data.frame.sz; dst->buf = src->data.frame.buf; + dst->have_sse = 0; + /* For alt-ref frame, don't store PSNR or increment frame_number */ + if (!(dst->flags & VPX_FRAME_IS_INVISIBLE)) { + dst->frame_number = ++ctx->frame_number; + dst->have_sse = ctx->have_sse; + if (ctx->have_sse) { + /* associate last-seen SSE to the frame. */ + /* Transfers ownership from ctx to dst. */ + /* WARNING! This makes the assumption that PSNR_PKT comes + just before the frame it refers to! */ + memcpy(dst->sse, ctx->sse, sizeof(dst->sse)); + ctx->have_sse = 0; + } + } else { + dst->frame_number = -1; /* sanity marker */ + } } /** @@ -438,6 +465,19 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, pkt->flags |= AV_PKT_FLAG_KEY; } else coded_frame->pict_type = AV_PICTURE_TYPE_P; + + if (cx_frame->have_sse) { + int i; + /* Beware of the Y/U/V/all order! */ + coded_frame->error[0] = cx_frame->sse[1]; + coded_frame->error[1] = cx_frame->sse[2]; + coded_frame->error[2] = cx_frame->sse[3]; + coded_frame->error[3] = 0; // alpha + for (i = 0; i < 4; ++i) { + avctx->error[i] += coded_frame->error[i]; + } + cx_frame->have_sse = 0; + } } else { return ret; } @@ -481,7 +521,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, /* avoid storing the frame when the list is empty and we haven't yet provided a frame for output */ av_assert0(!ctx->coded_frame_list); - cx_pktcpy(&cx_frame, pkt); + cx_pktcpy(&cx_frame, pkt, ctx); size = storeframe(avctx, &cx_frame, pkt_out, coded_frame); if (size < 0) return size; @@ -494,7 +534,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, "Frame queue element alloc failed\n"); return AVERROR(ENOMEM); } - cx_pktcpy(cx_frame, pkt); + cx_pktcpy(cx_frame, pkt, ctx); cx_frame->buf = av_malloc(cx_frame->sz); if (!cx_frame->buf) { @@ -521,7 +561,14 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out, stats->sz += pkt->data.twopass_stats.sz; break; } - case VPX_CODEC_PSNR_PKT: //FIXME add support for CODEC_FLAG_PSNR + case VPX_CODEC_PSNR_PKT: + av_assert0(!ctx->have_sse); + ctx->sse[0] = pkt->data.psnr.sse[0]; + ctx->sse[1] = pkt->data.psnr.sse[1]; + ctx->sse[2] = pkt->data.psnr.sse[2]; + ctx->sse[3] = pkt->data.psnr.sse[3]; + ctx->have_sse = 1; + break; case VPX_CODEC_CUSTOM_PKT: //ignore unsupported/unrecognized packet types break; |