This is necessary to preserve the quality information currently exported
with coded_frame. Add the new side data to every encoder that needs it,
and use it in avconv.

Signed-off-by: Vittorio Giovara <[email protected]>
---
 avconv.c                   | 13 ++++++++++---
 avconv.h                   |  3 +++
 doc/APIchanges             |  3 +++
 libavcodec/avcodec.h       |  7 +++++++
 libavcodec/dnxhdenc.c      |  7 ++++++-
 libavcodec/libx264.c       |  9 ++++++++-
 libavcodec/libxavs.c       |  6 ++++++
 libavcodec/libxvid.c       |  6 ++++++
 libavcodec/mpegvideo_enc.c |  7 +++++++
 libavcodec/svq1enc.c       |  6 ++++++
 libavcodec/version.h       |  4 ++--
 libavformat/dump.c         |  3 +++
 12 files changed, 67 insertions(+), 7 deletions(-)

diff --git a/avconv.c b/avconv.c
index 5efa80d..b4654fc 100644
--- a/avconv.c
+++ b/avconv.c
@@ -335,6 +335,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;
+    }
 
     while (bsfc) {
         AVPacket new_pkt = *pkt;
@@ -622,7 +627,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->frame_number;
-        fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, 
enc->coded_frame->quality / (float)FF_QP2LAMBDA);
+        fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number,
+                ost->quality / (float)FF_QP2LAMBDA);
         if (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)));
 
@@ -907,8 +913,9 @@ static void print_report(int is_last_report, int64_t 
timer_start)
         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);
         }
diff --git a/avconv.h b/avconv.h
index 5fddf98..0d6f293 100644
--- a/avconv.h
+++ b/avconv.h
@@ -361,6 +361,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/doc/APIchanges b/doc/APIchanges
index 0ddfb11..f54d604 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil:     2014-08-09
 
 API changes, most recent first:
 
+2015-xx-xx - xxxxxxx - lavc 56.30.0 - avcodec.h
+  Add AV_PKT_DATA_QUALITY_FACTOR to export the quality value of an AVPacket.
+
 2015-xx-xx - xxxxxxx - lavf 56.20.0 - avio.h
   Add avio_put_str16be.
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 7191e8b..6594d77 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -930,6 +930,13 @@ enum AVPacketSideDataType {
      * to enum AVAudioServiceType.
      */
     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,
 };
 
 typedef struct AVPacketSideData {
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index 2edb226..ac7f419 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -1028,7 +1028,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_packet(pkt, ctx->cid_table->frame_size)) < 0) {
         av_log(avctx, AV_LOG_ERROR,
@@ -1084,6 +1084,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 6b31616..8972c8a 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -268,8 +268,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 9b80243..cd3a904 100644
--- a/libavcodec/libxavs.c
+++ b/libavcodec/libxavs.c
@@ -119,6 +119,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;
@@ -193,6 +194,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 = ctx->qscale * FF_QP2LAMBDA;
+
     x4->out_frame_count++;
     *got_packet = ret;
     return 0;
diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c
index 5282ea7..b440ac2 100644
--- a/libavcodec/libxvid.c
+++ b/libavcodec/libxvid.c
@@ -743,6 +743,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 5375873..2309720 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -1583,6 +1583,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket 
*pkt,
 
     /* output? */
     if (s->new_picture.f->data[0]) {
+        uint8_t *sd;
         if (!pkt->data &&
             (ret = ff_alloc_packet(pkt, 
s->mb_width*s->mb_height*MAX_MB_BYTES)) < 0)
             return ret;
@@ -1624,6 +1625,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 82e2f74..ebbc54e 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -569,6 +569,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, 
AVPacket *pkt,
 {
     SVQ1EncContext *const s = avctx->priv_data;
     int i, ret;
+    uint8_t *sd;
 
     if (!pkt->data &&
         (ret = av_new_packet(pkt, s->y_block_width * s->y_block_height *
@@ -611,6 +612,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 b0643cc..67be2ce 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 29
-#define LIBAVCODEC_VERSION_MICRO  1
+#define LIBAVCODEC_VERSION_MINOR 30
+#define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavformat/dump.c b/libavformat/dump.c
index 22ae586..878eae8 100644
--- a/libavformat/dump.c
+++ b/libavformat/dump.c
@@ -359,6 +359,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);
-- 
1.9.5 (Apple Git-50.3)

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to