[FFmpeg-devel] [PATCH] Replace AV_PKT_DATA_QUALITY_FACTOR by AV_PKT_DATA_QUALITY_STATS

Michael Niedermayer michaelni at gmx.at
Tue Jul 21 13:37:59 CEST 2015


From: Michael Niedermayer <michael at niedermayer.cc>

The stats are a superset of the quality factor, also allowing the picture type and encoder "PSNR" stats to be exported
This also replaces the native by fixed little endian order for the affected side data

TODO: set pict_type for all encoders which export AV_PKT_DATA_QUALITY_STATS

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>
---
 doc/APIchanges             |    5 +++--
 ffmpeg.c                   |    4 ++--
 libavcodec/avcodec.h       |   15 +++++++++++----
 libavcodec/avpacket.c      |   25 +++++++++++++++++++++++++
 libavcodec/dnxhdenc.c      |    5 +----
 libavcodec/internal.h      |    2 ++
 libavcodec/libx264.c       |    6 +-----
 libavcodec/libxavs.c       |    5 +----
 libavcodec/libxvid.c       |   25 +++++++++++++------------
 libavcodec/mpegvideo_enc.c |    6 +-----
 libavcodec/svq1enc.c       |    5 +----
 libavcodec/version.h       |    4 ++--
 libavformat/dump.c         |    4 ++--
 13 files changed, 65 insertions(+), 46 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index a7d9952..e90e23e 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,8 +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-xx-xx - xxxxxxx - lavc 56.51.100 - avcodec.h
+  Add AV_PKT_DATA_QUALITY_STATS to export the quality value, PSNR, and pict_type
+  of an AVPacket.
 
 2015-07-16 - xxxxxxxx - lavc 56.49.100
   Add av_codec_get_codec_properties(), FF_CODEC_PROPERTY_LOSSLESS
diff --git a/ffmpeg.c b/ffmpeg.c
index ce9cac7..751c7d3 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -669,9 +669,9 @@ 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,
+        uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
                                               NULL);
-        ost->quality = sd ? *(int *)sd : -1;
+        ost->quality = sd ? AV_RL32(sd) : -1;
     }
 
     if (bsfc)
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 6cfbea4..a86a152 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1055,11 +1055,16 @@ 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).
+     * This side data contains quality related information from the encoder.
+     * @code
+     * u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad).
+     * u8    picture type
+     * u8    error count
+     * u16   reserved
+     * u64le[error count] sum of squared differences between encoder in and output
+     * @endcode
      */
-    AV_PKT_DATA_QUALITY_FACTOR,
+    AV_PKT_DATA_QUALITY_STATS,
 
     /**
      * Recommmends skipping the specified number of samples
@@ -1126,6 +1131,8 @@ enum AVPacketSideDataType {
     AV_PKT_DATA_METADATA_UPDATE,
 };
 
+#define AV_PKT_DATA_QUALITY_FACTOR please_use_AV_PKT_DATA_QUALITY_STATS_which_is_a_superset_of_it
+
 typedef struct AVPacketSideData {
     uint8_t *data;
     int      size;
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index aae67c5..6ba9c0b 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -602,3 +602,28 @@ void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
     if (pkt->convergence_duration > 0)
         pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb);
 }
+
+int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type)
+{
+    uint8_t *side_data;
+    int side_data_size;
+    int i;
+
+    side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, &side_data_size);
+    if (!side_data) {
+        side_data_size = 4+4+8*error_count;
+        side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,
+                                            side_data_size);
+    }
+
+    if (!side_data || side_data_size < 4+4+8*error_count)
+        return AVERROR(ENOMEM);
+
+    AV_WL32(side_data   , quality  );
+    side_data[4] = pict_type;
+    side_data[5] = error_count;
+    for (i = 0; i<error_count; i++)
+        AV_WL64(side_data+8 + 8*i , error[i]);
+
+    return 0;
+}
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index 9302402..3f5f17f 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -1115,10 +1115,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-    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;
+    ff_side_data_set_encoder_stats(pkt, ctx->qscale * FF_QP2LAMBDA, NULL, 0, 0);
 
     pkt->flags |= AV_PKT_FLAG_KEY;
     *got_packet = 1;
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index f3dafc0..e0b40f1 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -298,4 +298,6 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt);
  */
 int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame);
 
+int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type);
+
 #endif /* AVCODEC_INTERNAL_H */
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 048edbf..3a55b5d 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -307,11 +307,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
 
     pkt->flags |= AV_PKT_FLAG_KEY*pic_out.b_keyframe;
     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;
+        ff_side_data_set_encoder_stats(pkt, (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA, NULL, 0, 0);
 
 #if FF_API_CODED_FRAME
 FF_DISABLE_DEPRECATION_WARNINGS
diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c
index a1b48c0..9c1c689 100644
--- a/libavcodec/libxavs.c
+++ b/libavcodec/libxavs.c
@@ -208,10 +208,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-    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;
+    ff_side_data_set_encoder_stats(pkt, (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA, NULL, 0, 0);
 
     x4->out_frame_count++;
     *got_packet = ret;
diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c
index 25c2476..6979346 100644
--- a/libavcodec/libxvid.c
+++ b/libavcodec/libxvid.c
@@ -771,27 +771,28 @@ 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;
+        int pict_type;
 
         *got_packet = 1;
 
-#if FF_API_CODED_FRAME
-FF_DISABLE_DEPRECATION_WARNINGS
-        avctx->coded_frame->quality = xvid_enc_stats.quant * FF_QP2LAMBDA;
         if (xvid_enc_stats.type == XVID_TYPE_PVOP)
-            avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P;
+            pict_type = AV_PICTURE_TYPE_P;
         else if (xvid_enc_stats.type == XVID_TYPE_BVOP)
-            avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B;
+            pict_type = AV_PICTURE_TYPE_B;
         else if (xvid_enc_stats.type == XVID_TYPE_SVOP)
-            avctx->coded_frame->pict_type = AV_PICTURE_TYPE_S;
+            pict_type = AV_PICTURE_TYPE_S;
         else
-            avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
+            pict_type = AV_PICTURE_TYPE_I;
+
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+        avctx->coded_frame->pict_type = pict_type;
+        avctx->coded_frame->quality = xvid_enc_stats.quant * FF_QP2LAMBDA;
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
+
+        ff_side_data_set_encoder_stats(pkt, xvid_enc_stats.quant * FF_QP2LAMBDA, NULL, 0, pict_type);
+
         if (xvid_enc_frame.out_flags & XVID_KEYFRAME) {
 #if FF_API_CODED_FRAME
 FF_DISABLE_DEPRECATION_WARNINGS
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 0143d9d..6939ce5 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -1786,11 +1786,7 @@ 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;
+        ff_side_data_set_encoder_stats(pkt, s->current_picture.f->quality, NULL, 0, s->pict_type);
 
         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 cb3bc45..6d5ff01 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -618,10 +618,7 @@ FF_DISABLE_DEPRECATION_WARNINGS
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-    sd = av_packet_new_side_data(pkt, AV_PKT_DATA_QUALITY_FACTOR, sizeof(int));
-    if (!sd)
-        return AVERROR(ENOMEM);
-    *(int *)sd = pict->quality;
+    ff_side_data_set_encoder_stats(pkt, pict->quality, NULL, 0, s->pict_type);
 
     svq1_write_header(s, s->pict_type);
     for (i = 0; i < 3; i++)
diff --git a/libavcodec/version.h b/libavcodec/version.h
index c79e2ba..399ee56 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  50
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MINOR  51
+#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 bb7779d..acf6bf6 100644
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -377,8 +377,8 @@ 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);
+        case AV_PKT_DATA_QUALITY_STATS:
+            av_log(ctx, AV_LOG_INFO, "quality factor: %d", AV_RL32(sd.data));
             break;
         default:
             av_log(ctx, AV_LOG_WARNING,
-- 
1.7.9.5



More information about the ffmpeg-devel mailing list