diff --git a/doc/APIchanges b/doc/APIchanges index 340515cd7c..a7d99524e0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2014-08-09 API changes, most recent first: +2015-xx-xx - xxxxxxx - lavc 56.33.0 - avcodec.h + Add AV_PKT_DATA_QUALITY_FACTOR to export the quality value of an AVPacket. + 2015-07-16 - xxxxxxxx - lavc 56.49.100 Add av_codec_get_codec_properties(), FF_CODEC_PROPERTY_LOSSLESS and FF_CODEC_PROPERTY_CLOSED_CAPTIONS diff --git a/ffmpeg.c b/ffmpeg.c index f9052ff7e3..635ac311e2 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -667,6 +667,11 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost) } ost->frame_number++; } + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + NULL); + ost->quality = sd ? *(int *)sd : -1; + } if (bsfc) av_packet_split_side_data(pkt); @@ -1257,7 +1262,8 @@ static void do_video_stats(OutputStream *ost, int frame_size) enc = ost->enc_ctx; if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { frame_number = ost->st->nb_frames; - fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame ? enc->coded_frame->quality / (float)FF_QP2LAMBDA : 0); + fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, + ost->quality / (float)FF_QP2LAMBDA); if (enc->coded_frame && (enc->flags&CODEC_FLAG_PSNR)) fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0] / (enc->width * enc->height * 255.0 * 255.0))); @@ -1548,8 +1554,9 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti float q = -1; ost = output_streams[i]; enc = ost->enc_ctx; - if (!ost->stream_copy && enc->coded_frame) - q = enc->coded_frame->quality / (float)FF_QP2LAMBDA; + if (!ost->stream_copy) + q = ost->quality / (float) FF_QP2LAMBDA; + if (vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q); av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", diff --git a/ffmpeg.h b/ffmpeg.h index cf2865fd2f..e43c985f52 100644 --- a/ffmpeg.h +++ b/ffmpeg.h @@ -456,6 +456,9 @@ typedef struct OutputStream { // number of frames/samples sent to the encoder uint64_t frames_encoded; uint64_t samples_encoded; + + /* packet quality factor */ + int quality; } OutputStream; typedef struct OutputFile { diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 62205c9896..cc2f3cce4d 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1054,6 +1054,13 @@ enum AVPacketSideDataType { */ AV_PKT_DATA_AUDIO_SERVICE_TYPE, + /** + * This side data contains an integer value representing the quality + * factor of the compressed frame. Allowed range is between 1 (good) + * and FF_LAMBDA_MAX (bad). + */ + AV_PKT_DATA_QUALITY_FACTOR, + /** * Recommmends skipping the specified number of samples * @code diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index bbb0065f8a..5eba9f65ed 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -1050,7 +1050,7 @@ static int dnxhd_encode_picture(AVCodecContext *avctx, AVPacket *pkt, DNXHDEncContext *ctx = avctx->priv_data; int first_field = 1; int offset, i, ret; - uint8_t *buf; + uint8_t *buf, *sd; if ((ret = ff_alloc_packet2(avctx, pkt, ctx->cid_table->frame_size)) < 0) return ret; @@ -1103,6 +1103,11 @@ encode_coding_unit: avctx->coded_frame->quality = ctx->qscale * FF_QP2LAMBDA; + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = ctx->qscale * FF_QP2LAMBDA; + pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 868b99e732..60938cf3c2 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -302,8 +302,15 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, } pkt->flags |= AV_PKT_FLAG_KEY*pic_out.b_keyframe; - if (ret) + if (ret) { + uint8_t *sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; + ctx->coded_frame->quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; + } *got_packet = ret; return 0; diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index ca9539a656..e26204ccbf 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -117,6 +117,7 @@ static int XAVS_frame(AVCodecContext *avctx, AVPacket *pkt, xavs_nal_t *nal; int nnal, i, ret; xavs_picture_t pic_out; + uint8_t *sd; x4->pic.img.i_csp = XAVS_CSP_I420; x4->pic.img.i_plane = 3; @@ -191,6 +192,11 @@ static int XAVS_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->coded_frame->quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA; + x4->out_frame_count++; *got_packet = ret; return 0; diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index 4574f380ba..976066c8a0 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -771,6 +771,12 @@ static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } if (xerr > 0) { + uint8_t *sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = xvid_enc_stats.quant * FF_QP2LAMBDA; + *got_packet = 1; avctx->coded_frame->quality = xvid_enc_stats.quant * FF_QP2LAMBDA; diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index fec4eca042..8ddfc02cf3 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -1731,6 +1731,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, /* output? */ if (s->new_picture.f->data[0]) { + uint8_t *sd; int growing_buffer = context_count == 1 && !pkt->data && !s->data_partitioning; int pkt_size = growing_buffer ? FFMAX(s->mb_width*s->mb_height*64+10000, avctx->internal->byte_buffer_size) - FF_INPUT_BUFFER_PADDING_SIZE : @@ -1781,6 +1782,12 @@ vbv_retry: frame_end(s); + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, + sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = s->current_picture.f->quality; + if (CONFIG_MJPEG_ENCODER && s->out_format == FMT_MJPEG) ff_mjpeg_encode_picture_trailer(&s->pb, s->header_bits); diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index a74d0e4e10..f391c95536 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -574,6 +574,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, { SVQ1EncContext *const s = avctx->priv_data; int i, ret; + uint8_t *sd; if ((ret = ff_alloc_packet2(avctx, pkt, s->y_block_width * s->y_block_height * MAX_MB_BYTES*3 + FF_MIN_BUFFER_SIZE)) < 0) @@ -613,6 +614,11 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, avctx->coded_frame->pict_type = s->pict_type; avctx->coded_frame->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int)); + if (!sd) + return AVERROR(ENOMEM); + *(int *)sd = pict->quality; + svq1_write_header(s, s->pict_type); for (i = 0; i < 3; i++) if (svq1_encode_plane(s, i, diff --git a/libavcodec/version.h b/libavcodec/version.h index 07b1ae30db..df0f25234a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,8 +29,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 56 -#define LIBAVCODEC_VERSION_MINOR 49 -#define LIBAVCODEC_VERSION_MICRO 101 +#define LIBAVCODEC_VERSION_MINOR 50 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \ diff --git a/libavformat/dump.c b/libavformat/dump.c index 1da29b9462..bb7779daf9 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -377,6 +377,9 @@ static void dump_sidedata(void *ctx, AVStream *st, const char *indent) av_log(ctx, AV_LOG_INFO, "audio service type: "); dump_audioservicetype(ctx, &sd); break; + case AV_PKT_DATA_QUALITY_FACTOR: + av_log(ctx, AV_LOG_INFO, "quality factor: %d", *(int *)sd.data); + break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d (%d bytes)", sd.type, sd.size);