]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mpegvideo_enc.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / mpegvideo_enc.c
index c780ffb598780cef7c1e68d46ef264bbc2264192..15fa9a22b8594e22d277581f703626367eec3dec 100644 (file)
@@ -43,6 +43,7 @@
 #include "flv.h"
 #include "mpeg4video.h"
 #include "internal.h"
+#include "bytestream.h"
 #include <limits.h>
 #include "sp5x.h"
 
@@ -79,11 +80,8 @@ void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64],
     for (qscale = qmin; qscale <= qmax; qscale++) {
         int i;
         if (dsp->fdct == ff_jpeg_fdct_islow_8 ||
-            dsp->fdct == ff_jpeg_fdct_islow_10
-#ifdef FAAN_POSTSCALE
-            || dsp->fdct == ff_faandct
-#endif
-            ) {
+            dsp->fdct == ff_jpeg_fdct_islow_10 ||
+            dsp->fdct == ff_faandct) {
             for (i = 0; i < 64; i++) {
                 const int j = dsp->idct_permutation[i];
                 /* 16 <= qscale * quant_matrix[i] <= 7905
@@ -95,11 +93,7 @@ void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64],
                 qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) /
                                         (qscale * quant_matrix[j]));
             }
-        } else if (dsp->fdct == ff_fdct_ifast
-#ifndef FAAN_POSTSCALE
-                   || dsp->fdct == ff_faandct
-#endif
-                   ) {
+        } else if (dsp->fdct == ff_fdct_ifast) {
             for (i = 0; i < 64; i++) {
                 const int j = dsp->idct_permutation[i];
                 /* 16 <= qscale * quant_matrix[i] <= 7905
@@ -137,11 +131,7 @@ void ff_convert_matrix(DSPContext *dsp, int (*qmat)[64],
 
         for (i = intra; i < 64; i++) {
             int64_t max = 8191;
-            if (dsp->fdct == ff_fdct_ifast
-#ifndef FAAN_POSTSCALE
-                || dsp->fdct == ff_faandct
-#endif
-               ) {
+            if (dsp->fdct == ff_fdct_ifast) {
                 max = (8191LL * ff_aanscales[i]) >> 14;
             }
             while (((max * qmat[qscale][i]) >> shift) > INT_MAX) {
@@ -400,7 +390,8 @@ av_cold int ff_MPV_encode_init(AVCodecContext *avctx)
 
     if ((!avctx->rc_max_rate) != (!avctx->rc_buffer_size)) {
         av_log(avctx, AV_LOG_ERROR, "Either both buffer size and max rate or neither must be specified\n");
-        return -1;
+        if (avctx->rc_max_rate && !avctx->rc_buffer_size)
+            return -1;
     }
 
     if (avctx->rc_min_rate && avctx->rc_max_rate != avctx->rc_min_rate) {
@@ -980,7 +971,7 @@ static int load_input_picture(MpegEncContext *s, AVFrame *pic_arg)
         if (i < 0)
             return i;
 
-        pic = (AVFrame *) &s->picture[i];
+        pic = &s->picture[i].f;
         pic->reference = 3;
 
         for (i = 0; i < 4; i++) {
@@ -995,7 +986,7 @@ static int load_input_picture(MpegEncContext *s, AVFrame *pic_arg)
         if (i < 0)
             return i;
 
-        pic = (AVFrame *) &s->picture[i];
+        pic = &s->picture[i].f;
         pic->reference = 3;
 
         if (ff_alloc_picture(s, (Picture *) pic, 0) < 0) {
@@ -1251,7 +1242,7 @@ static int select_input_picture(MpegEncContext *s)
                                s->input_picture[0]->f.type == FF_BUFFER_TYPE_INTERNAL);
 
                         s->avctx->release_buffer(s->avctx,
-                                                 (AVFrame *) s->input_picture[0]);
+                                                 &s->input_picture[0]->f);
                     }
 
                     emms_c();
@@ -1384,13 +1375,13 @@ no_output_pic:
             /* mark us unused / free shared pic */
             if (s->reordered_input_picture[0]->f.type == FF_BUFFER_TYPE_INTERNAL)
                 s->avctx->release_buffer(s->avctx,
-                                         (AVFrame *) s->reordered_input_picture[0]);
+                                         &s->reordered_input_picture[0]->f);
             for (i = 0; i < 4; i++)
                 s->reordered_input_picture[0]->f.data[i] = NULL;
             s->reordered_input_picture[0]->f.type = 0;
 
-            copy_picture_attributes(s, (AVFrame *) pic,
-                                    (AVFrame *) s->reordered_input_picture[0]);
+            copy_picture_attributes(s, &pic->f,
+                                    &s->reordered_input_picture[0]->f);
 
             s->current_picture_ptr = pic;
         } else {
@@ -1417,7 +1408,7 @@ no_output_pic:
 }
 
 int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
-                          const AVFrame *pic_arg, int *got_packet)
+                          AVFrame *pic_arg, int *got_packet)
 {
     MpegEncContext *s = avctx->priv_data;
     int i, stuffing_count, ret;
@@ -1434,9 +1425,14 @@ int ff_MPV_encode_picture(AVCodecContext *avctx, AVPacket *pkt,
 
     /* output? */
     if (s->new_picture.f.data[0]) {
-        if (!pkt->data &&
-            (ret = ff_alloc_packet(pkt, s->mb_width*s->mb_height*(MAX_MB_BYTES+100)+10000)) < 0)
+        if ((ret = ff_alloc_packet2(avctx, pkt, s->mb_width*s->mb_height*(MAX_MB_BYTES+100)+10000)) < 0)
             return ret;
+        if (s->mb_info) {
+            s->mb_info_ptr = av_packet_new_side_data(pkt,
+                                 AV_PKT_DATA_H263_MB_INFO,
+                                 s->mb_width*s->mb_height*12);
+            s->prev_mb_info = s->last_mb_info = s->mb_info_size = 0;
+        }
 
         for (i = 0; i < context_count; i++) {
             int start_y = s->thread_context[i]->start_mb_y;
@@ -1594,16 +1590,18 @@ vbv_retry:
         avctx->frame_bits  = s->frame_bits;
 
         pkt->pts = s->current_picture.f.pts;
-        if (!s->low_delay) {
+        if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) {
             if (!s->current_picture.f.coded_picture_number)
                 pkt->dts = pkt->pts - s->dts_delta;
             else
                 pkt->dts = s->reordered_pts;
-            s->reordered_pts = s->input_picture[0]->f.pts;
+            s->reordered_pts = pkt->pts;
         } else
             pkt->dts = pkt->pts;
         if (s->current_picture.f.key_frame)
             pkt->flags |= AV_PKT_FLAG_KEY;
+        if (s->mb_info)
+            av_packet_shrink_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, s->mb_info_size);
     } else {
         assert((put_bits_ptr(&s->pb) == s->pb.buf));
         s->frame_bits = 0;
@@ -2348,6 +2346,49 @@ static void write_slice_end(MpegEncContext *s){
         s->misc_bits+= get_bits_diff(s);
 }
 
+static void write_mb_info(MpegEncContext *s)
+{
+    uint8_t *ptr = s->mb_info_ptr + s->mb_info_size - 12;
+    int offset = put_bits_count(&s->pb);
+    int mba  = s->mb_x + s->mb_width * (s->mb_y % s->gob_index);
+    int gobn = s->mb_y / s->gob_index;
+    int pred_x, pred_y;
+    if (CONFIG_H263_ENCODER)
+        ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
+    bytestream_put_le32(&ptr, offset);
+    bytestream_put_byte(&ptr, s->qscale);
+    bytestream_put_byte(&ptr, gobn);
+    bytestream_put_le16(&ptr, mba);
+    bytestream_put_byte(&ptr, pred_x); /* hmv1 */
+    bytestream_put_byte(&ptr, pred_y); /* vmv1 */
+    /* 4MV not implemented */
+    bytestream_put_byte(&ptr, 0); /* hmv2 */
+    bytestream_put_byte(&ptr, 0); /* vmv2 */
+}
+
+static void update_mb_info(MpegEncContext *s, int startcode)
+{
+    if (!s->mb_info)
+        return;
+    if (put_bits_count(&s->pb) - s->prev_mb_info*8 >= s->mb_info*8) {
+        s->mb_info_size += 12;
+        s->prev_mb_info = s->last_mb_info;
+    }
+    if (startcode) {
+        s->prev_mb_info = put_bits_count(&s->pb)/8;
+        /* This might have incremented mb_info_size above, and we return without
+         * actually writing any info into that slot yet. But in that case,
+         * this will be called again at the start of the after writing the
+         * start code, actually writing the mb info. */
+        return;
+    }
+
+    s->last_mb_info = put_bits_count(&s->pb)/8;
+    if (!s->mb_info_size)
+        s->mb_info_size += 12;
+    write_mb_info(s);
+}
+
 static int encode_thread(AVCodecContext *c, void *arg){
     MpegEncContext *s= *(void**)arg;
     int mb_x, mb_y, pdif = 0;
@@ -2498,6 +2539,7 @@ static int encode_thread(AVCodecContext *c, void *arg){
                         int number_mb = (mb_y - s->resync_mb_y)*s->mb_width + mb_x - s->resync_mb_x;
                         s->avctx->rtp_callback(s->avctx, s->ptr_lastgob, current_packet_size, number_mb);
                     }
+                    update_mb_info(s, 1);
 
                     switch(s->codec_id){
                     case CODEC_ID_MPEG4:
@@ -2541,6 +2583,8 @@ static int encode_thread(AVCodecContext *c, void *arg){
             s->mb_skipped=0;
             s->dquant=0; //only for QP_RD
 
+            update_mb_info(s, 0);
+
             if (mb_type & (mb_type-1) || (s->mpv_flags & FF_MPV_FLAG_QP_RD)) { // more than 1 MB type possible or FF_MPV_FLAG_QP_RD
                 int next_block=0;
                 int pb_bits_count, pb2_bits_count, tex_pb_bits_count;
@@ -3462,11 +3506,7 @@ static int dct_quantize_trellis_c(MpegEncContext *s,
         int dct_coeff= FFABS(block[ scantable[i] ]);
         int best_score=256*256*256*120;
 
-        if (   s->dsp.fdct == ff_fdct_ifast
-#ifndef FAAN_POSTSCALE
-            || s->dsp.fdct == ff_faandct
-#endif
-           )
+        if (s->dsp.fdct == ff_fdct_ifast)
             dct_coeff= (dct_coeff*ff_inv_aanscales[ scantable[i] ]) >> 12;
         zero_distortion= dct_coeff*dct_coeff;
 
@@ -4117,6 +4157,7 @@ int ff_dct_quantize_c(MpegEncContext *s,
 static const AVOption h263_options[] = {
     { "obmc",         "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
     { "structured_slices","Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE},
+    { "mb_info",      "emit macroblock info for RFC 2190 packetization, the parameter value is the maximum payload size", OFFSET(mb_info), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, VE },
     FF_MPV_COMMON_OPTS
     { NULL },
 };
@@ -4164,9 +4205,9 @@ AVCodec ff_h263p_encoder = {
     .init           = ff_MPV_encode_init,
     .encode2        = ff_MPV_encode_picture,
     .close          = ff_MPV_encode_end,
-    .capabilities = CODEC_CAP_SLICE_THREADS,
-    .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
-    .long_name= NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"),
+    .capabilities   = CODEC_CAP_SLICE_THREADS,
+    .pix_fmts       = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+    .long_name      = NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"),
     .priv_class     = &h263p_class,
 };
 
@@ -4180,8 +4221,8 @@ AVCodec ff_msmpeg4v2_encoder = {
     .init           = ff_MPV_encode_init,
     .encode2        = ff_MPV_encode_picture,
     .close          = ff_MPV_encode_end,
-    .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
-    .long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"),
+    .pix_fmts       = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+    .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"),
     .priv_class     = &msmpeg4v2_class,
 };
 
@@ -4195,8 +4236,8 @@ AVCodec ff_msmpeg4v3_encoder = {
     .init           = ff_MPV_encode_init,
     .encode2        = ff_MPV_encode_picture,
     .close          = ff_MPV_encode_end,
-    .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
-    .long_name= NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"),
+    .pix_fmts       = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+    .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"),
     .priv_class     = &msmpeg4v3_class,
 };
 
@@ -4210,7 +4251,7 @@ AVCodec ff_wmv1_encoder = {
     .init           = ff_MPV_encode_init,
     .encode2        = ff_MPV_encode_picture,
     .close          = ff_MPV_encode_end,
-    .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE},
-    .long_name= NULL_IF_CONFIG_SMALL("Windows Media Video 7"),
+    .pix_fmts       = (const enum PixelFormat[]){ PIX_FMT_YUV420P, PIX_FMT_NONE },
+    .long_name      = NULL_IF_CONFIG_SMALL("Windows Media Video 7"),
     .priv_class     = &wmv1_class,
 };