diff mbox series

[FFmpeg-devel,7/7] Handle AVID MJPEG streams directly in the MJPEG decoder.

Message ID 20201212154555.21243-7-anton@khirnov.net
State New
Headers show
Series [FFmpeg-devel,1/7] tools/target_dec_fuzzer: use non-obsolete decoding API | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Anton Khirnov Dec. 12, 2020, 3:45 p.m. UTC
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.
---
 libavcodec/avrndec.c  | 74 ++-----------------------------------------
 libavcodec/mjpegdec.c | 11 +++++++
 libavcodec/version.h  |  2 +-
 libavformat/avidec.c  |  6 ++++
 libavformat/isom.c    |  2 +-
 libavformat/version.h |  2 +-
 tests/fate/video.mak  |  2 +-
 7 files changed, 23 insertions(+), 76 deletions(-)

Comments

James Almer Dec. 13, 2020, 12:17 a.m. UTC | #1
On 12/12/2020 12:45 PM, Anton Khirnov wrote:
> 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.
> ---
>   libavcodec/avrndec.c  | 74 ++-----------------------------------------
>   libavcodec/mjpegdec.c | 11 +++++++
>   libavcodec/version.h  |  2 +-
>   libavformat/avidec.c  |  6 ++++
>   libavformat/isom.c    |  2 +-
>   libavformat/version.h |  2 +-
>   tests/fate/video.mak  |  2 +-
>   7 files changed, 23 insertions(+), 76 deletions(-)
> 
> diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c
> index d85e3c2000..a80851cefa 100644
> --- a/libavcodec/avrndec.c
> +++ b/libavcodec/avrndec.c
> @@ -21,13 +21,10 @@
>   
>   #include "avcodec.h"
>   #include "internal.h"
> -#include "mjpeg.h"
> -#include "mjpegdec.h"

You can probably also remove the jpegtables dep in configure and the 
mjpegdec.o entry in Makefile for the avrn decoder.

> +
>   #include "libavutil/imgutils.h"
>   
>   typedef struct {
> -    AVCodecContext *mjpeg_avctx;
> -    int is_mjpeg;
>       int interlace;
>       int tff;
>   } AVRnContext;
> @@ -37,42 +34,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;
>   
> @@ -89,15 +50,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)
>   {
> @@ -107,28 +59,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) {
> @@ -167,8 +97,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,
>   };
> diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
> index ea3f125cca..39a05db35b 100644
> --- a/libavcodec/mjpegdec.c
> +++ b/libavcodec/mjpegdec.c
> @@ -484,6 +484,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)
> @@ -2897,6 +2902,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;
>   
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index 5b92afe60a..abfbd63ac8 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -29,7 +29,7 @@
>   
>   #define LIBAVCODEC_VERSION_MAJOR  58
>   #define LIBAVCODEC_VERSION_MINOR 115
> -#define LIBAVCODEC_VERSION_MICRO 102
> +#define LIBAVCODEC_VERSION_MICRO 103
>   
>   #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
>                                                  LIBAVCODEC_VERSION_MINOR, \
> diff --git a/libavformat/avidec.c b/libavformat/avidec.c
> index 7e527e15ee..0c5fddd597 100644
> --- a/libavformat/avidec.c
> +++ b/libavformat/avidec.c
> @@ -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;
> diff --git a/libavformat/isom.c b/libavformat/isom.c
> index d1ef6e3407..db84bb417b 100644
> --- a/libavformat/isom.c
> +++ b/libavformat/isom.c
> @@ -115,7 +115,7 @@ 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', '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) */
> diff --git a/libavformat/version.h b/libavformat/version.h
> index b43193bcb1..a2b5901e74 100644
> --- a/libavformat/version.h
> +++ b/libavformat/version.h
> @@ -33,7 +33,7 @@
>   // Also please add any ticket numbers that you believe might be affected here
>   #define LIBAVFORMAT_VERSION_MAJOR  58
>   #define LIBAVFORMAT_VERSION_MINOR  65
> -#define LIBAVFORMAT_VERSION_MICRO 100
> +#define LIBAVFORMAT_VERSION_MICRO 101
>   
>   #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
>                                                  LIBAVFORMAT_VERSION_MINOR, \
> diff --git a/tests/fate/video.mak b/tests/fate/video.mak
> index a5f3107c38..0984b929cb 100644
> --- a/tests/fate/video.mak
> +++ b/tests/fate/video.mak
> @@ -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
>
Anton Khirnov Dec. 13, 2020, 9:44 a.m. UTC | #2
Quoting James Almer (2020-12-13 01:17:52)
> On 12/12/2020 12:45 PM, Anton Khirnov wrote:
> > 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.
> > ---
> >   libavcodec/avrndec.c  | 74 ++-----------------------------------------
> >   libavcodec/mjpegdec.c | 11 +++++++
> >   libavcodec/version.h  |  2 +-
> >   libavformat/avidec.c  |  6 ++++
> >   libavformat/isom.c    |  2 +-
> >   libavformat/version.h |  2 +-
> >   tests/fate/video.mak  |  2 +-
> >   7 files changed, 23 insertions(+), 76 deletions(-)
> > 
> > diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c
> > index d85e3c2000..a80851cefa 100644
> > --- a/libavcodec/avrndec.c
> > +++ b/libavcodec/avrndec.c
> > @@ -21,13 +21,10 @@
> >   
> >   #include "avcodec.h"
> >   #include "internal.h"
> > -#include "mjpeg.h"
> > -#include "mjpegdec.h"
> 
> You can probably also remove the jpegtables dep in configure and the 
> mjpegdec.o entry in Makefile for the avrn decoder.

Right, done that locally.
Michael Niedermayer Dec. 15, 2020, 12:13 a.m. UTC | #3
On Sat, Dec 12, 2020 at 04:45:55PM +0100, Anton Khirnov wrote:
> 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.
> ---
>  libavcodec/avrndec.c  | 74 ++-----------------------------------------
>  libavcodec/mjpegdec.c | 11 +++++++
>  libavcodec/version.h  |  2 +-
>  libavformat/avidec.c  |  6 ++++
>  libavformat/isom.c    |  2 +-
>  libavformat/version.h |  2 +-
>  tests/fate/video.mak  |  2 +-
>  7 files changed, 23 insertions(+), 76 deletions(-)

breaks:
./ffmpeg -i ~/tickets/1527/24bpp.mov  whatever.mov

...
Press [q] to stop, [?] for help
[avrn @ 0x5625d111bbc0] packet too small
Error while decoding stream #0:0: Invalid data found when processing input
[avrn @ 0x5625d111bbc0] packet too small
Error while decoding stream #0:0: Invalid data found when processing input
[avrn @ 0x5625d111bbc0] packet too small
Error while decoding stream #0:0: Invalid data found when processing input
[avrn @ 0x5625d111bbc0] packet too small
...




[...]
James Almer Dec. 15, 2020, 1:04 a.m. UTC | #4
On 12/14/2020 9:13 PM, Michael Niedermayer wrote:
> On Sat, Dec 12, 2020 at 04:45:55PM +0100, Anton Khirnov wrote:
>> 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.
>> ---
>>   libavcodec/avrndec.c  | 74 ++-----------------------------------------
>>   libavcodec/mjpegdec.c | 11 +++++++
>>   libavcodec/version.h  |  2 +-
>>   libavformat/avidec.c  |  6 ++++
>>   libavformat/isom.c    |  2 +-
>>   libavformat/version.h |  2 +-
>>   tests/fate/video.mak  |  2 +-
>>   7 files changed, 23 insertions(+), 76 deletions(-)
> 
> breaks:
> ./ffmpeg -i ~/tickets/1527/24bpp.mov  whatever.mov
> 
> ...
> Press [q] to stop, [?] for help
> [avrn @ 0x5625d111bbc0] packet too small
> Error while decoding stream #0:0: Invalid data found when processing input
> [avrn @ 0x5625d111bbc0] packet too small
> Error while decoding stream #0:0: Invalid data found when processing input
> [avrn @ 0x5625d111bbc0] packet too small
> Error while decoding stream #0:0: Invalid data found when processing input
> [avrn @ 0x5625d111bbc0] packet too small

Reenabling...

> diff --git a/libavformat/isom.c b/libavformat/isom.c
> index d1ef6e3407..db84bb417b 100644
> --- a/libavformat/isom.c
> +++ b/libavformat/isom.c
> @@ -115,7 +115,7 @@ 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', '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) */

...this line here seems to fix it (The riff.c entry for AVRn selects the 
avrn decoder otherwise).
diff mbox series

Patch

diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c
index d85e3c2000..a80851cefa 100644
--- a/libavcodec/avrndec.c
+++ b/libavcodec/avrndec.c
@@ -21,13 +21,10 @@ 
 
 #include "avcodec.h"
 #include "internal.h"
-#include "mjpeg.h"
-#include "mjpegdec.h"
+
 #include "libavutil/imgutils.h"
 
 typedef struct {
-    AVCodecContext *mjpeg_avctx;
-    int is_mjpeg;
     int interlace;
     int tff;
 } AVRnContext;
@@ -37,42 +34,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;
 
@@ -89,15 +50,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)
 {
@@ -107,28 +59,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) {
@@ -167,8 +97,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,
 };
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index ea3f125cca..39a05db35b 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -484,6 +484,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)
@@ -2897,6 +2902,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;
 
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 5b92afe60a..abfbd63ac8 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@ 
 
 #define LIBAVCODEC_VERSION_MAJOR  58
 #define LIBAVCODEC_VERSION_MINOR 115
-#define LIBAVCODEC_VERSION_MICRO 102
+#define LIBAVCODEC_VERSION_MICRO 103
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 7e527e15ee..0c5fddd597 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -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;
diff --git a/libavformat/isom.c b/libavformat/isom.c
index d1ef6e3407..db84bb417b 100644
--- a/libavformat/isom.c
+++ b/libavformat/isom.c
@@ -115,7 +115,7 @@  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', '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) */
diff --git a/libavformat/version.h b/libavformat/version.h
index b43193bcb1..a2b5901e74 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -33,7 +33,7 @@ 
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  58
 #define LIBAVFORMAT_VERSION_MINOR  65
-#define LIBAVFORMAT_VERSION_MICRO 100
+#define LIBAVFORMAT_VERSION_MICRO 101
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
diff --git a/tests/fate/video.mak b/tests/fate/video.mak
index a5f3107c38..0984b929cb 100644
--- a/tests/fate/video.mak
+++ b/tests/fate/video.mak
@@ -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