]> git.sesse.net Git - ffmpeg/commitdiff
Handle AVID MJPEG streams directly in the MJPEG decoder.
authorAnton Khirnov <anton@khirnov.net>
Sat, 12 Dec 2020 14:09:10 +0000 (15:09 +0100)
committerAnton Khirnov <anton@khirnov.net>
Thu, 25 Feb 2021 10:46:28 +0000 (11:46 +0100)
AVID streams - currently handled by the AVRN decoder - can be (depending
on extradata contents) either MJPEG or raw video. To decode the MJPEG
variant, the AVRN decoder currently instantiates a MJPEG decoder
internally and forwards decoded frames to the caller (possibly after
cropping them).

This is suboptimal, because the AVRN decoder does not forward all the
features of the internal MJPEG decoder, such as direct rendering.
Handling such forwarding in a full and generic manner would be quite
hard, so it is simpler to just handle those streams in the MJPEG decoder
directly.

The AVRN decoder, which now handles only the raw streams, can now be
marked as supporting direct rendering.

This also removes the last remaining internal use of the obsolete
decoding API.

configure
libavcodec/avrndec.c
libavcodec/mjpegdec.c
libavcodec/version.h
libavformat/avidec.c
libavformat/isom_tags.c
tests/fate/video.mak

index 5250445325ddfedd65ec961ec545f3dc2b8387a3..d11942fced116800956ac42ebe61ac342b422e5b 100755 (executable)
--- a/configure
+++ b/configure
@@ -2688,7 +2688,6 @@ atrac3p_decoder_select="mdct sinewin"
 atrac3pal_decoder_select="mdct sinewin"
 atrac9_decoder_select="mdct"
 av1_decoder_select="cbs_av1"
-avrn_decoder_select="mjpeg_decoder"
 bink_decoder_select="blockdsp hpeldsp"
 binkaudio_dct_decoder_select="mdct rdft dct sinewin wma_freqs"
 binkaudio_rdft_decoder_select="mdct rdft sinewin wma_freqs"
index 9380d8688509bae99f94c6276a912fd7f901216d..26cf6b752c0cfaa1da2ba0e7286d26595508268d 100644 (file)
@@ -24,8 +24,6 @@
 #include "libavutil/imgutils.h"
 
 typedef struct {
-    AVCodecContext *mjpeg_avctx;
-    int is_mjpeg;
     int interlace;
     int tff;
 } AVRnContext;
@@ -35,42 +33,6 @@ static av_cold int init(AVCodecContext *avctx)
     AVRnContext *a = avctx->priv_data;
     int ret;
 
-    // Support "Resolution 1:1" for Avid AVI Codec
-    a->is_mjpeg = avctx->extradata_size < 31 || memcmp(&avctx->extradata[28], "1:1", 3);
-
-    if(!a->is_mjpeg && avctx->lowres) {
-        av_log(avctx, AV_LOG_ERROR, "lowres is not possible with rawvideo\n");
-        return AVERROR(EINVAL);
-    }
-
-    if(a->is_mjpeg) {
-        const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
-        AVDictionary *thread_opt = NULL;
-        if (!codec) {
-            av_log(avctx, AV_LOG_ERROR, "MJPEG codec not found\n");
-            return AVERROR_DECODER_NOT_FOUND;
-        }
-
-        a->mjpeg_avctx = avcodec_alloc_context3(codec);
-        if (!a->mjpeg_avctx)
-            return AVERROR(ENOMEM);
-
-        av_dict_set(&thread_opt, "threads", "1", 0); // Is this needed ?
-        a->mjpeg_avctx->refcounted_frames = 1;
-        a->mjpeg_avctx->flags = avctx->flags;
-        a->mjpeg_avctx->idct_algo = avctx->idct_algo;
-        a->mjpeg_avctx->lowres = avctx->lowres;
-        a->mjpeg_avctx->width = avctx->width;
-        a->mjpeg_avctx->height = avctx->height;
-
-        if ((ret = avcodec_open2(a->mjpeg_avctx, codec, &thread_opt)) < 0) {
-            av_log(avctx, AV_LOG_ERROR, "MJPEG codec failed to open\n");
-        }
-        av_dict_free(&thread_opt);
-
-        return ret;
-    }
-
     if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
         return ret;
 
@@ -87,15 +49,6 @@ static av_cold int init(AVCodecContext *avctx)
     return 0;
 }
 
-static av_cold int end(AVCodecContext *avctx)
-{
-    AVRnContext *a = avctx->priv_data;
-
-    avcodec_free_context(&a->mjpeg_avctx);
-
-    return 0;
-}
-
 static int decode_frame(AVCodecContext *avctx, void *data,
                         int *got_frame, AVPacket *avpkt)
 {
@@ -105,28 +58,6 @@ static int decode_frame(AVCodecContext *avctx, void *data,
     int buf_size       = avpkt->size;
     int y, ret, true_height;
 
-    if(a->is_mjpeg) {
-        ret = avcodec_decode_video2(a->mjpeg_avctx, data, got_frame, avpkt);
-
-        if (ret >= 0 && *got_frame && avctx->width <= p->width && avctx->height <= p->height) {
-            int shift = p->height - avctx->height;
-            int subsample_h, subsample_v;
-
-            av_pix_fmt_get_chroma_sub_sample(p->format, &subsample_h, &subsample_v);
-
-            p->data[0] += p->linesize[0] * shift;
-            if (p->data[2]) {
-                p->data[1] += p->linesize[1] * (shift>>subsample_v);
-                p->data[2] += p->linesize[2] * (shift>>subsample_v);
-            }
-
-            p->width  = avctx->width;
-            p->height = avctx->height;
-        }
-        avctx->pix_fmt = a->mjpeg_avctx->pix_fmt;
-        return ret;
-    }
-
     true_height    = buf_size / (2*avctx->width);
 
     if(buf_size < 2*avctx->width * avctx->height) {
@@ -165,8 +96,8 @@ AVCodec ff_avrn_decoder = {
     .id             = AV_CODEC_ID_AVRN,
     .priv_data_size = sizeof(AVRnContext),
     .init           = init,
-    .close          = end,
     .decode         = decode_frame,
     .max_lowres     = 3,
+    .capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
index 256393a68fa1668352c455ea9ffbd22d81e888ff..79c7d6e6cfe3872fa8bed79c1b97c76d4533eb18 100644 (file)
@@ -450,6 +450,11 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
         size_change = 0;
     }
 
+    if ((s->avctx->codec_tag == MKTAG('A', 'V', 'R', 'n') ||
+         s->avctx->codec_tag == MKTAG('A', 'V', 'D', 'J')) &&
+        s->orig_height < s->avctx->height)
+        s->avctx->height = s->orig_height;
+
     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)
@@ -2855,6 +2860,12 @@ the_end:
             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   = avctx->coded_height;
+        frame->crop_top = frame->height - s->orig_height;
+    }
 
     ret = 0;
 
index a0c9241fe65c1c2d5715f9b6726e76d564c23049..e5a5ec8abcef79d89e479169b232178e19510fbb 100644 (file)
@@ -29,7 +29,7 @@
 
 #define LIBAVCODEC_VERSION_MAJOR  58
 #define LIBAVCODEC_VERSION_MINOR 125
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
index 547eb63b1b92084a375d8096daa1ccba8d1214ce..5ea6160eef4b12380979376faddf1d73092d9bd0 100644 (file)
@@ -838,6 +838,12 @@ static int avi_read_header(AVFormatContext *s)
                         st->codecpar->codec_tag == MKTAG('H', '2', '6', '5'))
                         st->need_parsing = AVSTREAM_PARSE_FULL;
 
+                    if (st->codecpar->codec_id  == AV_CODEC_ID_AVRN &&
+                        st->codecpar->codec_tag == MKTAG('A', 'V', 'R', 'n') &&
+                        (st->codecpar->extradata_size < 31 ||
+                          memcmp(&st->codecpar->extradata[28], "1:1", 3)))
+                        st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
+
                     if (st->codecpar->codec_tag == 0 && st->codecpar->height > 0 &&
                         st->codecpar->extradata_size < 1U << 30) {
                         st->codecpar->extradata_size += 9;
index 75c3ee2b32126ca97a3e1be7351ea797b72aee44..1666b9d4a50fb7a3f467782532d26949031c2bcf 100644 (file)
@@ -69,8 +69,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = {
 
     { AV_CODEC_ID_MJPEG,  MKTAG('j', 'p', 'e', 'g') }, /* PhotoJPEG */
     { AV_CODEC_ID_MJPEG,  MKTAG('m', 'j', 'p', 'a') }, /* Motion-JPEG (format A) */
-    { AV_CODEC_ID_AVRN ,  MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
-/*  { AV_CODEC_ID_MJPEG,  MKTAG('A', 'V', 'R', 'n') }, *//* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
+    { AV_CODEC_ID_MJPEG,  MKTAG('A', 'V', 'D', 'J') }, /* MJPEG with alpha-channel (AVID JFIF meridien compressed) */
+    { AV_CODEC_ID_MJPEG,  MKTAG('A', 'V', 'R', 'n') }, /* MJPEG with alpha-channel (AVID ABVB/Truevision NuVista) */
     { AV_CODEC_ID_MJPEG,  MKTAG('d', 'm', 'b', '1') }, /* Motion JPEG OpenDML */
     { AV_CODEC_ID_MJPEGB, MKTAG('m', 'j', 'p', 'b') }, /* Motion-JPEG (format B) */
 
index 4b2c4ab66506e14df90ba68d27f3f1f1e0dbf929..d6b5770abae82963cd558f5ad86f96da0d7928ca 100644 (file)
@@ -46,7 +46,7 @@ fate-auravision-v2: CMD = framecrc -i $(TARGET_SAMPLES)/auravision/salma-hayek-i
 FATE_VIDEO-$(call DEMDEC, AVI, AVRN) += fate-avid-interlaced
 fate-avid-interlaced: CMD = framecrc -i $(TARGET_SAMPLES)/avid/avid_ntsc_interlaced.avi
 
-FATE_VIDEO-$(call DEMDEC, MOV, AVRN) += fate-avid-meridian
+FATE_VIDEO-$(call DEMDEC, MOV, MJPEG) += fate-avid-meridian
 fate-avid-meridian: CMD = framecrc -i $(TARGET_SAMPLES)/avid/avidmeridianntsc.mov
 
 FATE_VIDEO-$(call DEMDEC, BETHSOFTVID, BETHSOFTVID) += fate-bethsoft-vid