X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmjpegdec.c;h=62684001649ff8ecbf854d1c488b2fb4316de5c5;hb=252500a78fe1a31abc79e6070d16f50382c39343;hp=cb5e2a9b9b0b02ec62c847107efe9ba8808916fc;hpb=2594f6a362c788a036dbf3e27d540d15fe7f72d0;p=ffmpeg diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index cb5e2a9b9b0..62684001649 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -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" @@ -50,29 +51,6 @@ #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,28 @@ 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); + ff_free_vlc(&s->vlcs[ht[i].class][ht[i].index]); + 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 +126,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); @@ -156,8 +138,9 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->buffer = NULL; s->start_code = -1; s->first_picture = 1; + s->seen_sof = 0; 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; @@ -172,7 +155,8 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) if (ff_mjpeg_decode_dht(s)) { av_log(avctx, AV_LOG_ERROR, "error using external huffman table, switching back to internal\n"); - init_default_huffman_tables(s); + if ((ret = init_default_huffman_tables(s)) < 0) + return ret; } } if (avctx->field_order == AV_FIELD_BB) { /* quicktime icefloe 019 */ @@ -183,7 +167,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 +236,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 +266,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 +275,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; } @@ -437,13 +430,14 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) memcpy(s->h_count, h_count, sizeof(h_count)); memcpy(s->v_count, v_count, sizeof(v_count)); s->interlaced = 0; + s->seen_sof = 0; s->got_picture = 0; /* 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 +449,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"); @@ -499,6 +504,11 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } } + if (s->bayer) { + if (pix_fmt_id != 0x11110000 && pix_fmt_id != 0x11000000) + goto unk_pixfmt; + } + switch (pix_fmt_id) { case 0x11110000: /* for bayer-encoded huffman lossless JPEGs embedded in DNGs */ if (!s->bayer) @@ -554,6 +564,7 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) case 0x12121100: case 0x22122100: case 0x21211100: + case 0x21112100: case 0x22211200: case 0x22221100: case 0x22112200: @@ -672,11 +683,13 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } else if (s->nb_components != 1) { av_log(s->avctx, AV_LOG_ERROR, "Unsupported number of components %d\n", s->nb_components); return AVERROR_PATCHWELCOME; - } else if (s->palette_index && s->bits <= 8) - s->avctx->pix_fmt = AV_PIX_FMT_PAL8; - else if (s->bits <= 8) - s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; - else + } else if (s->bits <= 8) { + avpriv_set_systematic_pal2(s->palette, s->avctx->pix_fmt); + if (s->palette_index) + s->avctx->pix_fmt = AV_PIX_FMT_PAL8; + else + s->avctx->pix_fmt = AV_PIX_FMT_GRAY8; + } else s->avctx->pix_fmt = AV_PIX_FMT_GRAY16; } @@ -710,26 +723,13 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) if (s->avctx->skip_frame == AVDISCARD_ALL) { s->picture_ptr->pict_type = AV_PICTURE_TYPE_I; s->picture_ptr->key_frame = 1; - s->got_picture = 1; + s->seen_sof = 1; return 0; } - - av_frame_unref(s->picture_ptr); - if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0) - return -1; - s->picture_ptr->pict_type = AV_PICTURE_TYPE_I; - s->picture_ptr->key_frame = 1; - s->got_picture = 1; - - for (i = 0; i < 4; i++) - s->linesize[i] = s->picture_ptr->linesize[i] << s->interlaced; - - ff_dlog(s->avctx, "%d %d %d %d %d %d\n", - s->width, s->height, s->linesize[0], s->linesize[1], - s->interlaced, s->avctx->height); - } + s->seen_sof = 1; + if ((s->rgb && !s->lossless && !s->ls) || (!s->rgb && s->ls && s->nb_components > 1) || (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 && !s->ls) @@ -755,18 +755,6 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) memset(s->coefs_finished, 0, sizeof(s->coefs_finished)); } - if (s->avctx->hwaccel) { - s->hwaccel_picture_private = - av_mallocz(s->avctx->hwaccel->frame_priv_data_size); - if (!s->hwaccel_picture_private) - return AVERROR(ENOMEM); - - ret = s->avctx->hwaccel->start_frame(s->avctx, s->raw_image_buffer, - s->raw_image_buffer_size); - if (ret < 0) - return ret; - } - return 0; } @@ -1621,12 +1609,44 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask, const int block_size = s->lossless ? 1 : 8; int ilv, prev_shift; - if (!s->got_picture) { + if (!s->seen_sof) { av_log(s->avctx, AV_LOG_WARNING, "Can not process SOS before SOF, skipping\n"); return -1; } + if (!s->got_picture || !s->interlaced || !(s->bottom_field == !s->interlace_polarity)) { + av_frame_unref(s->picture_ptr); + if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0) + return -1; + s->picture_ptr->pict_type = AV_PICTURE_TYPE_I; + s->picture_ptr->key_frame = 1; + + for (i = 0; i < 4; i++) + s->linesize[i] = s->picture_ptr->linesize[i] << s->interlaced; + + if (s->picture_ptr->format == AV_PIX_FMT_PAL8) + memcpy(s->picture_ptr->data[1], s->palette, sizeof(s->palette)); + + s->got_picture = 1; + + ff_dlog(s->avctx, "%d %d %d %d %d %d\n", + s->width, s->height, s->linesize[0], s->linesize[1], + s->interlaced, s->avctx->height); + + if (s->avctx->hwaccel && !s->hwaccel_picture_private) { + s->hwaccel_picture_private = + av_mallocz(s->avctx->hwaccel->frame_priv_data_size); + if (!s->hwaccel_picture_private) + return AVERROR(ENOMEM); + + ret = s->avctx->hwaccel->start_frame(s->avctx, s->raw_image_buffer, + s->raw_image_buffer_size); + if (ret < 0) + return ret; + } + } + if (reference) { if (reference->width != s->picture_ptr->width || reference->height != s->picture_ptr->height || @@ -2079,28 +2099,26 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) /* Allocate if this is the first APP2 we've seen. */ if (s->iccnum == 0) { - s->iccdata = av_mallocz(nummarkers * sizeof(*(s->iccdata))); - s->iccdatalens = av_mallocz(nummarkers * sizeof(*(s->iccdatalens))); - if (!s->iccdata || !s->iccdatalens) { + if (!FF_ALLOCZ_TYPED_ARRAY(s->iccentries, nummarkers)) { av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data arrays\n"); return AVERROR(ENOMEM); } s->iccnum = nummarkers; } - if (s->iccdata[seqno - 1]) { + if (s->iccentries[seqno - 1].data) { av_log(s->avctx, AV_LOG_WARNING, "Duplicate ICC sequence number\n"); goto out; } - s->iccdatalens[seqno - 1] = len; - s->iccdata[seqno - 1] = av_malloc(len); - if (!s->iccdata[seqno - 1]) { + s->iccentries[seqno - 1].length = len; + s->iccentries[seqno - 1].data = av_malloc(len); + if (!s->iccentries[seqno - 1].data) { av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data buffer\n"); return AVERROR(ENOMEM); } - memcpy(s->iccdata[seqno - 1], align_get_bits(&s->gb), len); + memcpy(s->iccentries[seqno - 1].data, align_get_bits(&s->gb), len); skip_bits(&s->gb, len << 3); len = 0; s->iccread++; @@ -2309,22 +2327,78 @@ static void reset_icc_profile(MJpegDecodeContext *s) { int i; - if (s->iccdata) + if (s->iccentries) { for (i = 0; i < s->iccnum; i++) - av_freep(&s->iccdata[i]); - av_freep(&s->iccdata); - av_freep(&s->iccdatalens); + av_freep(&s->iccentries[i].data); + av_freep(&s->iccentries); + } s->iccread = 0; 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; @@ -2335,7 +2409,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); @@ -2344,8 +2419,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, @@ -2357,7 +2436,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", @@ -2493,7 +2572,9 @@ eoi_parser: break; } if (avctx->skip_frame == AVDISCARD_ALL) { + s->seen_sof = 0; s->got_picture = 0; + ret = AVERROR(EAGAIN); goto the_end_no_picture; } if (s->avctx->hwaccel) { @@ -2505,22 +2586,17 @@ eoi_parser: } if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0) return ret; - *got_frame = 1; + s->seen_sof = 0; 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; @@ -2571,6 +2647,7 @@ skip: av_log(avctx, AV_LOG_FATAL, "No JPEG data found in image\n"); return AVERROR_INVALIDDATA; fail: + s->seen_sof = 0; s->got_picture = 0; return ret; the_end: @@ -2757,7 +2834,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; @@ -2773,9 +2850,9 @@ the_end: /* Sum size of all parts. */ for (i = 0; i < s->iccnum; i++) - total_size += s->iccdatalens[i]; + total_size += s->iccentries[i].length; - 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); @@ -2783,21 +2860,39 @@ the_end: /* Reassemble the parts, which are now in-order. */ for (i = 0; i < s->iccnum; i++) { - memcpy(sd->data + offset, s->iccdata[i], s->iccdatalens[i]); - offset += s->iccdatalens[i]; + memcpy(sd->data + offset, s->iccentries[i].data, s->iccentries[i].length); + offset += s->iccentries[i].length; } } - 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; @@ -2813,6 +2908,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); @@ -2831,6 +2930,7 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) reset_icc_profile(s); av_freep(&s->hwaccel_picture_private); + av_freep(&s->jls_state); return 0; } @@ -2838,7 +2938,11 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) static void decode_flush(AVCodecContext *avctx) { MJpegDecodeContext *s = avctx->priv_data; + s->seen_sof = 0; s->got_picture = 0; + + s->smv_next_frame = 0; + av_frame_unref(s->smv_frame); } #if CONFIG_MJPEG_DECODER @@ -2865,15 +2969,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 @@ -2893,10 +2997,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