]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mjpegdec.c
avcodec/qtrleenc: Use keyframe when no previous frame is available
[ffmpeg] / libavcodec / mjpegdec.c
index e7a4e08c1cfc989ab2dbd3806332fa2203f5d1c7..5583d2aa353a6a29809616909cc0b843ecc44ab2 100644 (file)
@@ -36,6 +36,7 @@
 #include "avcodec.h"
 #include "blockdsp.h"
 #include "copy_block.h"
+#include "decode.h"
 #include "hwconfig.h"
 #include "idctdsp.h"
 #include "internal.h"
 #include "bytestream.h"
 
 
-static int build_vlc(VLC *vlc, const uint8_t *bits_table,
-                     const uint8_t *val_table, int nb_codes,
-                     int use_static, int is_ac)
-{
-    uint8_t huff_size[256] = { 0 };
-    uint16_t huff_code[256];
-    uint16_t huff_sym[256];
-    int i;
-
-    av_assert0(nb_codes <= 256);
-
-    ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table);
-
-    for (i = 0; i < 256; i++)
-        huff_sym[i] = i + 16 * is_ac;
-
-    if (is_ac)
-        huff_sym[0] = 16 * 256;
-
-    return ff_init_vlc_sparse(vlc, 9, nb_codes, huff_size, 1, 1,
-                              huff_code, 2, 2, huff_sym, 2, 2, use_static);
-}
-
 static int init_default_huffman_tables(MJpegDecodeContext *s)
 {
     static const struct {
@@ -80,28 +58,27 @@ static int init_default_huffman_tables(MJpegDecodeContext *s)
         int index;
         const uint8_t *bits;
         const uint8_t *values;
-        int codes;
         int length;
     } ht[] = {
         { 0, 0, avpriv_mjpeg_bits_dc_luminance,
-                avpriv_mjpeg_val_dc, 12, 12 },
+                avpriv_mjpeg_val_dc, 12 },
         { 0, 1, avpriv_mjpeg_bits_dc_chrominance,
-                avpriv_mjpeg_val_dc, 12, 12 },
+                avpriv_mjpeg_val_dc, 12 },
         { 1, 0, avpriv_mjpeg_bits_ac_luminance,
-                avpriv_mjpeg_val_ac_luminance,   251, 162 },
+                avpriv_mjpeg_val_ac_luminance,   162 },
         { 1, 1, avpriv_mjpeg_bits_ac_chrominance,
-                avpriv_mjpeg_val_ac_chrominance, 251, 162 },
+                avpriv_mjpeg_val_ac_chrominance, 162 },
         { 2, 0, avpriv_mjpeg_bits_ac_luminance,
-                avpriv_mjpeg_val_ac_luminance,   251, 162 },
+                avpriv_mjpeg_val_ac_luminance,   162 },
         { 2, 1, avpriv_mjpeg_bits_ac_chrominance,
-                avpriv_mjpeg_val_ac_chrominance, 251, 162 },
+                avpriv_mjpeg_val_ac_chrominance, 162 },
     };
     int i, ret;
 
     for (i = 0; i < FF_ARRAY_ELEMS(ht); i++) {
-        ret = build_vlc(&s->vlcs[ht[i].class][ht[i].index],
-                        ht[i].bits, ht[i].values, ht[i].codes,
-                        0, ht[i].class == 1);
+        ret = ff_mjpeg_build_vlc(&s->vlcs[ht[i].class][ht[i].index],
+                                 ht[i].bits, ht[i].values,
+                                 ht[i].class == 1, s->avctx);
         if (ret < 0)
             return ret;
 
@@ -148,6 +125,10 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
         s->picture_ptr = s->picture;
     }
 
+    s->pkt = av_packet_alloc();
+    if (!s->pkt)
+        return AVERROR(ENOMEM);
+
     s->avctx = avctx;
     ff_blockdsp_init(&s->bdsp, avctx);
     ff_hpeldsp_init(&s->hdsp, avctx->flags);
@@ -157,7 +138,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
     s->start_code    = -1;
     s->first_picture = 1;
     s->got_picture   = 0;
-    s->org_height    = avctx->coded_height;
+    s->orig_height    = avctx->coded_height;
     avctx->chroma_sample_location = AVCHROMA_LOC_CENTER;
     avctx->colorspace = AVCOL_SPC_BT470BG;
     s->hwaccel_pix_fmt = s->hwaccel_sw_pix_fmt = AV_PIX_FMT_NONE;
@@ -183,7 +164,19 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
             s->interlace_polarity = 1;
     }
 
-    if (   avctx->extradata_size > 8
+    if (avctx->codec_id == AV_CODEC_ID_SMVJPEG) {
+        if (avctx->extradata_size >= 4)
+            s->smv_frames_per_jpeg = AV_RL32(avctx->extradata);
+
+        if (s->smv_frames_per_jpeg <= 0) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid number of frames per jpeg.\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        s->smv_frame = av_frame_alloc();
+        if (!s->smv_frame)
+            return AVERROR(ENOMEM);
+    } else if (avctx->extradata_size > 8
         && AV_RL32(avctx->extradata) == 0x2C
         && AV_RL32(avctx->extradata+4) == 0x18) {
         parse_avid(s, avctx->extradata, avctx->extradata_size);
@@ -240,7 +233,7 @@ int ff_mjpeg_decode_dqt(MJpegDecodeContext *s)
 /* decode huffman tables and build VLC decoders */
 int ff_mjpeg_decode_dht(MJpegDecodeContext *s)
 {
-    int len, index, i, class, n, v, code_max;
+    int len, index, i, class, n, v;
     uint8_t bits_table[17];
     uint8_t val_table[256];
     int ret = 0;
@@ -270,11 +263,8 @@ int ff_mjpeg_decode_dht(MJpegDecodeContext *s)
         if (len < n || n > 256)
             return AVERROR_INVALIDDATA;
 
-        code_max = 0;
         for (i = 0; i < n; i++) {
             v = get_bits(&s->gb, 8);
-            if (v > code_max)
-                code_max = v;
             val_table[i] = v;
         }
         len -= n;
@@ -282,15 +272,15 @@ int ff_mjpeg_decode_dht(MJpegDecodeContext *s)
         /* build VLC and flush previous vlc if present */
         ff_free_vlc(&s->vlcs[class][index]);
         av_log(s->avctx, AV_LOG_DEBUG, "class=%d index=%d nb_codes=%d\n",
-               class, index, code_max + 1);
-        if ((ret = build_vlc(&s->vlcs[class][index], bits_table, val_table,
-                             code_max + 1, 0, class > 0)) < 0)
+               class, index, n);
+        if ((ret = ff_mjpeg_build_vlc(&s->vlcs[class][index], bits_table,
+                                      val_table, class > 0, s->avctx)) < 0)
             return ret;
 
         if (class > 0) {
             ff_free_vlc(&s->vlcs[2][index]);
-            if ((ret = build_vlc(&s->vlcs[2][index], bits_table, val_table,
-                                 code_max + 1, 0, 0)) < 0)
+            if ((ret = ff_mjpeg_build_vlc(&s->vlcs[2][index], bits_table,
+                                          val_table, 0, s->avctx)) < 0)
                 return ret;
         }
 
@@ -442,8 +432,8 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
         /* test interlaced mode */
         if (s->first_picture   &&
             (s->multiscope != 2 || s->avctx->time_base.den >= 25 * s->avctx->time_base.num) &&
-            s->org_height != 0 &&
-            s->height < ((s->org_height * 3) / 4)) {
+            s->orig_height != 0 &&
+            s->height < ((s->orig_height * 3) / 4)) {
             s->interlaced                    = 1;
             s->bottom_field                  = s->interlace_polarity;
             s->picture_ptr->interlaced_frame = 1;
@@ -455,11 +445,22 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
         if (ret < 0)
             return ret;
 
+        if ((s->avctx->codec_tag == MKTAG('A', 'V', 'R', 'n') ||
+             s->avctx->codec_tag == MKTAG('A', 'V', 'D', 'J')) &&
+            s->orig_height < height)
+            s->avctx->height = AV_CEIL_RSHIFT(s->orig_height, s->avctx->lowres);
+
         s->first_picture = 0;
     } else {
         size_change = 0;
     }
 
+    if (s->avctx->codec_id == AV_CODEC_ID_SMVJPEG) {
+        s->avctx->height = s->avctx->coded_height / s->smv_frames_per_jpeg;
+        if (s->avctx->height <= 0)
+            return AVERROR_INVALIDDATA;
+    }
+
     if (s->got_picture && s->interlaced && (s->bottom_field == !s->interlace_polarity)) {
         if (s->progressive) {
             avpriv_request_sample(s->avctx, "progressively coded interlaced picture");
@@ -559,6 +560,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
         case 0x12121100:
         case 0x22122100:
         case 0x21211100:
+        case 0x21112100:
         case 0x22211200:
         case 0x22221100:
         case 0x22112200:
@@ -2324,12 +2326,68 @@ static void reset_icc_profile(MJpegDecodeContext *s)
     s->iccnum  = 0;
 }
 
-int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
-                          AVPacket *avpkt)
+// SMV JPEG just stacks several output frames into one JPEG picture
+// we handle that by setting up the cropping parameters appropriately
+static int smv_process_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+    MJpegDecodeContext *s = avctx->priv_data;
+    int ret;
+
+    if (s->smv_next_frame > 0) {
+        av_assert0(s->smv_frame->buf[0]);
+        av_frame_unref(frame);
+        ret = av_frame_ref(frame, s->smv_frame);
+        if (ret < 0)
+            return ret;
+    } else {
+        av_assert0(frame->buf[0]);
+        av_frame_unref(s->smv_frame);
+        ret = av_frame_ref(s->smv_frame, frame);
+        if (ret < 0)
+            return ret;
+    }
+
+    av_assert0((s->smv_next_frame + 1) * avctx->height <= avctx->coded_height);
+
+    frame->width       = avctx->coded_width;
+    frame->height      = avctx->coded_height;
+    frame->crop_top    = FFMIN(s->smv_next_frame * avctx->height, frame->height);
+    frame->crop_bottom = frame->height - (s->smv_next_frame + 1) * avctx->height;
+
+    s->smv_next_frame = (s->smv_next_frame + 1) % s->smv_frames_per_jpeg;
+
+    if (s->smv_next_frame == 0)
+        av_frame_unref(s->smv_frame);
+
+    return 0;
+}
+
+static int mjpeg_get_packet(AVCodecContext *avctx)
+{
+    MJpegDecodeContext *s = avctx->priv_data;
+    int ret;
+
+    av_packet_unref(s->pkt);
+    ret = ff_decode_get_packet(avctx, s->pkt);
+    if (ret < 0)
+        return ret;
+
+#if CONFIG_SP5X_DECODER || CONFIG_AMV_DECODER
+    if (avctx->codec_id == AV_CODEC_ID_SP5X ||
+        avctx->codec_id == AV_CODEC_ID_AMV) {
+        ret = ff_sp5x_process_packet(avctx, s->pkt);
+        if (ret < 0)
+            return ret;
+    }
+#endif
+
+    s->buf_size = s->pkt->size;
+
+    return 0;
+}
+
+int ff_mjpeg_receive_frame(AVCodecContext *avctx, AVFrame *frame)
 {
-    AVFrame     *frame = data;
-    const uint8_t *buf = avpkt->data;
-    int buf_size       = avpkt->size;
     MJpegDecodeContext *s = avctx->priv_data;
     const uint8_t *buf_end, *buf_ptr;
     const uint8_t *unescaped_buf_ptr;
@@ -2340,7 +2398,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     int ret = 0;
     int is16bit;
 
-    s->buf_size = buf_size;
+    if (avctx->codec_id == AV_CODEC_ID_SMVJPEG && s->smv_next_frame > 0)
+        return smv_process_frame(avctx, frame);
 
     av_dict_free(&s->exif_metadata);
     av_freep(&s->stereo3d);
@@ -2349,8 +2408,12 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     if (s->iccnum != 0)
         reset_icc_profile(s);
 
-    buf_ptr = buf;
-    buf_end = buf + buf_size;
+    ret = mjpeg_get_packet(avctx);
+    if (ret < 0)
+        return ret;
+
+    buf_ptr = s->pkt->data;
+    buf_end = s->pkt->data + s->pkt->size;
     while (buf_ptr < buf_end) {
         /* find start next marker */
         start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end,
@@ -2362,7 +2425,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         } else if (unescaped_buf_size > INT_MAX / 8) {
             av_log(avctx, AV_LOG_ERROR,
                    "MJPEG packet 0x%x too big (%d/%d), corrupt data?\n",
-                   start_code, unescaped_buf_size, buf_size);
+                   start_code, unescaped_buf_size, s->pkt->size);
             return AVERROR_INVALIDDATA;
         }
         av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%"PTRDIFF_SPECIFIER"\n",
@@ -2499,6 +2562,7 @@ eoi_parser:
             }
             if (avctx->skip_frame == AVDISCARD_ALL) {
                 s->got_picture = 0;
+                ret = AVERROR(EAGAIN);
                 goto the_end_no_picture;
             }
             if (s->avctx->hwaccel) {
@@ -2510,22 +2574,16 @@ eoi_parser:
             }
             if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0)
                 return ret;
-            *got_frame = 1;
             s->got_picture = 0;
 
-            if (!s->lossless) {
+            frame->pkt_dts = s->pkt->dts;
+
+            if (!s->lossless && avctx->debug & FF_DEBUG_QP) {
                 int qp = FFMAX3(s->qscale[0],
                                 s->qscale[1],
                                 s->qscale[2]);
-                int qpw = (s->width + 15) / 16;
-                AVBufferRef *qp_table_buf = av_buffer_alloc(qpw);
-                if (qp_table_buf) {
-                    memset(qp_table_buf->data, qp, qpw);
-                    av_frame_set_qp_table(data, qp_table_buf, 0, FF_QSCALE_TYPE_MPEG1);
-                }
 
-                if(avctx->debug & FF_DEBUG_QP)
-                    av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", qp);
+                av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", qp);
             }
 
             goto the_end;
@@ -2762,7 +2820,7 @@ the_end:
     }
 
     if (s->stereo3d) {
-        AVStereo3D *stereo = av_stereo3d_create_side_data(data);
+        AVStereo3D *stereo = av_stereo3d_create_side_data(frame);
         if (stereo) {
             stereo->type  = s->stereo3d->type;
             stereo->flags = s->stereo3d->flags;
@@ -2780,7 +2838,7 @@ the_end:
         for (i = 0; i < s->iccnum; i++)
             total_size += s->iccdatalens[i];
 
-        sd = av_frame_new_side_data(data, AV_FRAME_DATA_ICC_PROFILE, total_size);
+        sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, total_size);
         if (!sd) {
             av_log(s->avctx, AV_LOG_ERROR, "Could not allocate frame side data\n");
             return AVERROR(ENOMEM);
@@ -2793,16 +2851,34 @@ the_end:
         }
     }
 
-    av_dict_copy(&((AVFrame *) data)->metadata, s->exif_metadata, 0);
+    av_dict_copy(&frame->metadata, s->exif_metadata, 0);
     av_dict_free(&s->exif_metadata);
 
+    if (avctx->codec_id == AV_CODEC_ID_SMVJPEG) {
+        ret = smv_process_frame(avctx, frame);
+        if (ret < 0) {
+            av_frame_unref(frame);
+            return ret;
+        }
+    }
+    if ((avctx->codec_tag == MKTAG('A', 'V', 'R', 'n') ||
+         avctx->codec_tag == MKTAG('A', 'V', 'D', 'J')) &&
+        avctx->coded_height > s->orig_height) {
+        frame->height   = AV_CEIL_RSHIFT(avctx->coded_height, avctx->lowres);
+        frame->crop_top = frame->height - avctx->height;
+    }
+
+    ret = 0;
+
 the_end_no_picture:
     av_log(avctx, AV_LOG_DEBUG, "decode frame unused %"PTRDIFF_SPECIFIER" bytes\n",
            buf_end - buf_ptr);
-//  return buf_end - buf_ptr;
-    return buf_ptr - buf;
+
+    return ret;
 }
 
+/* mxpeg may call the following function (with a blank MJpegDecodeContext)
+ * even without having called ff_mjpeg_decode_init(). */
 av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
 {
     MJpegDecodeContext *s = avctx->priv_data;
@@ -2818,6 +2894,10 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
     } else if (s->picture_ptr)
         av_frame_unref(s->picture_ptr);
 
+    av_packet_free(&s->pkt);
+
+    av_frame_free(&s->smv_frame);
+
     av_freep(&s->buffer);
     av_freep(&s->stereo3d);
     av_freep(&s->ljpeg_buffer);
@@ -2844,6 +2924,9 @@ static void decode_flush(AVCodecContext *avctx)
 {
     MJpegDecodeContext *s = avctx->priv_data;
     s->got_picture = 0;
+
+    s->smv_next_frame = 0;
+    av_frame_unref(s->smv_frame);
 }
 
 #if CONFIG_MJPEG_DECODER
@@ -2870,15 +2953,15 @@ AVCodec ff_mjpeg_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .decode         = ff_mjpeg_decode_frame,
+    .receive_frame  = ff_mjpeg_receive_frame,
     .flush          = decode_flush,
     .capabilities   = AV_CODEC_CAP_DR1,
     .max_lowres     = 3,
     .priv_class     = &mjpegdec_class,
     .profiles       = NULL_IF_CONFIG_SMALL(ff_mjpeg_profiles),
-    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
-                      FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
-    .hw_configs     = (const AVCodecHWConfigInternal*[]) {
+    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
+                      FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_SETS_PKT_DTS,
+    .hw_configs     = (const AVCodecHWConfigInternal *const []) {
 #if CONFIG_MJPEG_NVDEC_HWACCEL
                         HWACCEL_NVDEC(mjpeg),
 #endif
@@ -2898,10 +2981,28 @@ AVCodec ff_thp_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .decode         = ff_mjpeg_decode_frame,
+    .receive_frame  = ff_mjpeg_receive_frame,
     .flush          = decode_flush,
     .capabilities   = AV_CODEC_CAP_DR1,
     .max_lowres     = 3,
-    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
+    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
+                      FF_CODEC_CAP_SETS_PKT_DTS,
+};
+#endif
+
+#if CONFIG_SMVJPEG_DECODER
+AVCodec ff_smvjpeg_decoder = {
+    .name           = "smvjpeg",
+    .long_name      = NULL_IF_CONFIG_SMALL("SMV JPEG"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_SMVJPEG,
+    .priv_data_size = sizeof(MJpegDecodeContext),
+    .init           = ff_mjpeg_decode_init,
+    .close          = ff_mjpeg_decode_end,
+    .receive_frame  = ff_mjpeg_receive_frame,
+    .flush          = decode_flush,
+    .capabilities   = AV_CODEC_CAP_DR1,
+    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING |
+                      FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP,
 };
 #endif