static int mjpeg_decode_app(MJpegDecodeContext *s)

{

    int len, id, i;



    len = get_bits(&s->gb, 16);

    if (len < 6)

        return AVERROR_INVALIDDATA;

    if (8 * len > get_bits_left(&s->gb))

        return AVERROR_INVALIDDATA;



    id   = get_bits_long(&s->gb, 32);

    len -= 6;



    if (s->avctx->debug & FF_DEBUG_STARTCODE) {

        char id_str[32];

        av_get_codec_tag_string(id_str, sizeof(id_str), av_bswap32(id));

        av_log(s->avctx, AV_LOG_DEBUG, "APPx (%s / %8X) len=%d\n", id_str, id, len);

    }



    /* Buggy AVID, it puts EOI only at every 10th frame. */

    /* Also, this fourcc is used by non-avid files too, it holds some

       information, but it's always present in AVID-created files. */

    if (id == AV_RB32("AVI1")) {

        /* structure:

            4bytes      AVI1

            1bytes      polarity

            1bytes      always zero

            4bytes      field_size

            4bytes      field_size_less_padding

        */

            s->buggy_avid = 1;

        i = get_bits(&s->gb, 8); len--;

        av_log(s->avctx, AV_LOG_DEBUG, "polarity %d\n", i);

#if 0

        skip_bits(&s->gb, 8);

        skip_bits(&s->gb, 32);

        skip_bits(&s->gb, 32);

        len -= 10;

#endif


    }



//    len -= 2;



    if (id == AV_RB32("JFIF")) {

        int t_w, t_h, v1, v2;



        skip_bits(&s->gb, 8); /* the trailing zero-byte */

        v1 = get_bits(&s->gb, 8);

        v2 = get_bits(&s->gb, 8);

        skip_bits(&s->gb, 8);



        s->avctx->sample_aspect_ratio.num = get_bits(&s->gb, 16);

        s->avctx->sample_aspect_ratio.den = get_bits(&s->gb, 16);

        if (   s->avctx->sample_aspect_ratio.num <= 0

            || s->avctx->sample_aspect_ratio.den <= 0) {

            s->avctx->sample_aspect_ratio.num = 0;

            s->avctx->sample_aspect_ratio.den = 1;

        }



        if (s->avctx->debug & FF_DEBUG_PICT_INFO)

            av_log(s->avctx, AV_LOG_INFO,

                   "mjpeg: JFIF header found (version: %x.%x) SAR=%d/%d\n",

                   v1, v2,

                   s->avctx->sample_aspect_ratio.num,

                   s->avctx->sample_aspect_ratio.den);



        len -= 8;

        if (len >= 2) {

            t_w = get_bits(&s->gb, 8);

            t_h = get_bits(&s->gb, 8);

            if (t_w && t_h) {

                /* skip thumbnail */

                if (len -10 - (t_w * t_h * 3) > 0)

                    len -= t_w * t_h * 3;

            }

            len -= 2;

        }


    }



    if (   id == AV_RB32("Adob")

        && len >= 7

        && show_bits(&s->gb, 8) == 'e'

        && show_bits_long(&s->gb, 32) != AV_RB32("e_CM")) {

        skip_bits(&s->gb,  8); /* 'e' */

        skip_bits(&s->gb, 16); /* version */

        skip_bits(&s->gb, 16); /* flags0 */

        skip_bits(&s->gb, 16); /* flags1 */

        s->adobe_transform = get_bits(&s->gb,  8);

        if (s->avctx->debug & FF_DEBUG_PICT_INFO)

            av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found, transform=%d\n", s->adobe_transform);

        len -= 7;


    }



    if (id == AV_RB32("LJIF")) {

        int rgb = s->rgb;

        int pegasus_rct = s->pegasus_rct;

        if (s->avctx->debug & FF_DEBUG_PICT_INFO)

            av_log(s->avctx, AV_LOG_INFO,

                   "Pegasus lossless jpeg header found\n");

        skip_bits(&s->gb, 16); /* version ? */

        skip_bits(&s->gb, 16); /* unknown always 0? */

        skip_bits(&s->gb, 16); /* unknown always 0? */

        skip_bits(&s->gb, 16); /* unknown always 0? */

        switch (i=get_bits(&s->gb, 8)) {

        case 1:

            rgb         = 1;

            pegasus_rct = 0;

            break;

        case 2:

            rgb         = 1;

            pegasus_rct = 1;

            break;

        default:

            av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace %d\n", i);

        }



        len -= 9;

        if (s->got_picture)

            if (rgb != s->rgb || pegasus_rct != s->pegasus_rct) {

                av_log(s->avctx, AV_LOG_WARNING, "Mismatching LJIF tag\n");


            }



        s->rgb = rgb;

        s->pegasus_rct = pegasus_rct;




    }

    if (id == AV_RL32("colr") && len > 0) {

        s->colr = get_bits(&s->gb, 8);

        if (s->avctx->debug & FF_DEBUG_PICT_INFO)

            av_log(s->avctx, AV_LOG_INFO, "COLR %d\n", s->colr);

        len --;


    }

    if (id == AV_RL32("xfrm") && len > 0) {

        s->xfrm = get_bits(&s->gb, 8);

        if (s->avctx->debug & FF_DEBUG_PICT_INFO)

            av_log(s->avctx, AV_LOG_INFO, "XFRM %d\n", s->xfrm);

        len --;


    }



    /* JPS extension by VRex */

    if (s->start_code == APP3 && id == AV_RB32("_JPS") && len >= 10) {

        int flags, layout, type;

        if (s->avctx->debug & FF_DEBUG_PICT_INFO)

            av_log(s->avctx, AV_LOG_INFO, "_JPSJPS_\n");



        skip_bits(&s->gb, 32); len -= 4;  /* JPS_ */

        skip_bits(&s->gb, 16); len -= 2;  /* block length */

        skip_bits(&s->gb, 8);             /* reserved */

        flags  = get_bits(&s->gb, 8);

        layout = get_bits(&s->gb, 8);

        type   = get_bits(&s->gb, 8);

        len -= 4;



        s->stereo3d = av_stereo3d_alloc();

        if (!s->stereo3d) {


        }

        if (type == 0) {

            s->stereo3d->type = AV_STEREO3D_2D;

        } else if (type == 1) {

            switch (layout) {

            case 0x01:

                s->stereo3d->type = AV_STEREO3D_LINES;

                break;

            case 0x02:

                s->stereo3d->type = AV_STEREO3D_SIDEBYSIDE;

                break;

            case 0x03:

                s->stereo3d->type = AV_STEREO3D_TOPBOTTOM;

                break;

            }

            if (!(flags & 0x04)) {

                s->stereo3d->flags = AV_STEREO3D_FLAG_INVERT;

            }

        }


    }



    /* EXIF metadata */

    if (s->start_code == APP1 && id == AV_RB32("Exif") && len >= 2) {

        GetByteContext gbytes;

        int ret, le, ifd_offset, bytes_read;

        const uint8_t *aligned;



        skip_bits(&s->gb, 16); // skip padding

        len -= 2;



        // init byte wise reading

        aligned = align_get_bits(&s->gb);

        bytestream2_init(&gbytes, aligned, len);



        // read TIFF header

        ret = ff_tdecode_header(&gbytes, &le, &ifd_offset);

        if (ret) {

            av_log(s->avctx, AV_LOG_ERROR, "mjpeg: invalid TIFF header in EXIF data\n");

        } else {

            bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);



            // read 0th IFD and store the metadata

            // (return values > 0 indicate the presence of subimage metadata)

            ret = avpriv_exif_decode_ifd(s->avctx, &gbytes, le, 0, &s->exif_metadata);

            if (ret < 0) {

                av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error decoding EXIF data\n");

            }

        }



        bytes_read = bytestream2_tell(&gbytes);

        skip_bits(&s->gb, bytes_read << 3);

        len -= bytes_read;




    }



    /* Apple MJPEG-A */

    if ((s->start_code == APP1) && (len > (0x28 - 8))) {

        id   = get_bits_long(&s->gb, 32);

        len -= 4;

        /* Apple MJPEG-A */

        if (id == AV_RB32("mjpg")) {

#if 0

            skip_bits(&s->gb, 32); /* field size */

            skip_bits(&s->gb, 32); /* pad field size */

            skip_bits(&s->gb, 32); /* next off */

            skip_bits(&s->gb, 32); /* quant off */

            skip_bits(&s->gb, 32); /* huff off */

            skip_bits(&s->gb, 32); /* image off */

            skip_bits(&s->gb, 32); /* scan off */

            skip_bits(&s->gb, 32); /* data off */

#endif

            if (s->avctx->debug & FF_DEBUG_PICT_INFO)

                av_log(s->avctx, AV_LOG_INFO, "mjpeg: Apple MJPEG-A header found\n");

        }

    }



out:

    /* slow but needed for extreme adobe jpegs */

    if (len < 0)

        av_log(s->avctx, AV_LOG_ERROR,

               "mjpeg: error, decode_app parser read over the end\n");

    while (--len > 0)

        skip_bits(&s->gb, 8);



    return 0;

}