summaryrefslogtreecommitdiff
path: root/libavcodec/mjpegdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/mjpegdec.c')
-rw-r--r--libavcodec/mjpegdec.c1119
1 files changed, 844 insertions, 275 deletions
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index d9a73d8426..1a774ddc61 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -8,20 +8,20 @@
* aspecting, new decode_frame mechanism and apple mjpeg-b support
* by Alex Beregszaszi
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -30,17 +30,20 @@
* MJPEG decoder.
*/
-#include <assert.h>
-
#include "libavutil/imgutils.h"
+#include "libavutil/avassert.h"
#include "libavutil/opt.h"
#include "avcodec.h"
#include "blockdsp.h"
+#include "copy_block.h"
#include "idctdsp.h"
#include "internal.h"
#include "mjpeg.h"
#include "mjpegdec.h"
#include "jpeglsdec.h"
+#include "tiff.h"
+#include "exif.h"
+#include "bytestream.h"
static int build_vlc(VLC *vlc, const uint8_t *bits_table,
@@ -52,7 +55,7 @@ static int build_vlc(VLC *vlc, const uint8_t *bits_table,
uint16_t huff_sym[256];
int i;
- assert(nb_codes <= 256);
+ av_assert0(nb_codes <= 256);
ff_mjpeg_build_huffman_codes(huff_size, huff_code, bits_table, val_table);
@@ -82,6 +85,17 @@ static void build_basic_mjpeg_vlc(MJpegDecodeContext *s)
avpriv_mjpeg_val_ac_chrominance, 251, 0, 0);
}
+static void parse_avid(MJpegDecodeContext *s, uint8_t *buf, int len)
+{
+ s->buggy_avid = 1;
+ if (len > 14 && buf[12] == 1) /* 1 - NTSC */
+ s->interlace_polarity = 1;
+ if (len > 14 && buf[12] == 2) /* 2 - PAL */
+ s->interlace_polarity = 0;
+ if (s->avctx->debug & FF_DEBUG_PICT_INFO)
+ av_log(s->avctx, AV_LOG_INFO, "AVID: len:%d %d\n", len, len > 14 ? buf[12] : -1);
+}
+
av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
{
MJpegDecodeContext *s = avctx->priv_data;
@@ -103,6 +117,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
s->buffer = NULL;
s->start_code = -1;
s->first_picture = 1;
+ s->got_picture = 0;
s->org_height = avctx->coded_height;
avctx->chroma_sample_location = AVCHROMA_LOC_CENTER;
avctx->colorspace = AVCOL_SPC_BT470BG;
@@ -110,19 +125,28 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
build_basic_mjpeg_vlc(s);
if (s->extern_huff) {
- int ret;
- av_log(avctx, AV_LOG_INFO, "mjpeg: using external huffman table\n");
+ av_log(avctx, AV_LOG_INFO, "using external huffman table\n");
init_get_bits(&s->gb, avctx->extradata, avctx->extradata_size * 8);
- if ((ret = ff_mjpeg_decode_dht(s))) {
+ if (ff_mjpeg_decode_dht(s)) {
av_log(avctx, AV_LOG_ERROR,
- "mjpeg: error using external huffman table\n");
- return ret;
+ "error using external huffman table, switching back to internal\n");
+ build_basic_mjpeg_vlc(s);
}
}
if (avctx->field_order == AV_FIELD_BB) { /* quicktime icefloe 019 */
s->interlace_polarity = 1; /* bottom field first */
- av_log(avctx, AV_LOG_DEBUG, "mjpeg bottom field first\n");
+ av_log(avctx, AV_LOG_DEBUG, "bottom field first\n");
+ } else if (avctx->field_order == AV_FIELD_UNKNOWN) {
+ if (avctx->codec_tag == AV_RL32("MJPG"))
+ s->interlace_polarity = 1;
+ }
+
+ if ( avctx->extradata_size > 8
+ && AV_RL32(avctx->extradata) == 0x2C
+ && AV_RL32(avctx->extradata+4) == 0x18) {
+ parse_avid(s, avctx->extradata, avctx->extradata_size);
}
+
if (avctx->codec->id == AV_CODEC_ID_AMV)
s->flipped = 1;
@@ -138,10 +162,10 @@ int ff_mjpeg_decode_dqt(MJpegDecodeContext *s)
len = get_bits(&s->gb, 16) - 2;
while (len >= 65) {
- /* only 8 bit precision handled */
- if (get_bits(&s->gb, 4) != 0) {
- av_log(s->avctx, AV_LOG_ERROR, "dqt: 16bit precision\n");
- return -1;
+ int pr = get_bits(&s->gb, 4);
+ if (pr > 1) {
+ av_log(s->avctx, AV_LOG_ERROR, "dqt: invalid precision\n");
+ return AVERROR_INVALIDDATA;
}
index = get_bits(&s->gb, 4);
if (index >= 4)
@@ -150,7 +174,7 @@ int ff_mjpeg_decode_dqt(MJpegDecodeContext *s)
/* read quant table */
for (i = 0; i < 64; i++) {
j = s->scantable.permutated[i];
- s->quant_matrixes[index][j] = get_bits(&s->gb, 8);
+ s->quant_matrixes[index][j] = get_bits(&s->gb, pr ? 16 : 8);
}
// XXX FIXME finetune, and perhaps add dc too
@@ -221,9 +245,15 @@ int ff_mjpeg_decode_dht(MJpegDecodeContext *s)
int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
{
int len, nb_components, i, width, height, pix_fmt_id, ret;
+ int h_count[MAX_COMPONENTS];
+ int v_count[MAX_COMPONENTS];
+
+ s->cur_scan = 0;
+ s->upscale_h = s->upscale_v = 0;
/* XXX: verify len field validity */
len = get_bits(&s->gb, 16);
+ s->avctx->bits_per_raw_sample =
s->bits = get_bits(&s->gb, 8);
if (s->pegasus_rct)
@@ -231,14 +261,17 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
if (s->bits == 9 && !s->pegasus_rct)
s->rct = 1; // FIXME ugly
- if (s->bits != 8 && !s->lossless) {
- av_log(s->avctx, AV_LOG_ERROR, "only 8 bits/component accepted\n");
+ if(s->lossless && s->avctx->lowres){
+ av_log(s->avctx, AV_LOG_ERROR, "lowres is not possible with lossless jpeg\n");
return -1;
}
height = get_bits(&s->gb, 16);
width = get_bits(&s->gb, 16);
+ if (s->avctx->codec_id == AV_CODEC_ID_AMV && (height&15))
+ avpriv_request_sample(s->avctx, "non mod 16 height AMV\n");
+
// HACK for odd_height.mov
if (s->interlaced && s->width == width && s->height == height + 1)
height= s->height;
@@ -267,28 +300,32 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
s->nb_components = nb_components;
s->h_max = 1;
s->v_max = 1;
+ memset(h_count, 0, sizeof(h_count));
+ memset(v_count, 0, sizeof(v_count));
for (i = 0; i < nb_components; i++) {
/* component id */
s->component_id[i] = get_bits(&s->gb, 8) - 1;
- s->h_count[i] = get_bits(&s->gb, 4);
- s->v_count[i] = get_bits(&s->gb, 4);
+ h_count[i] = get_bits(&s->gb, 4);
+ v_count[i] = get_bits(&s->gb, 4);
/* compute hmax and vmax (only used in interleaved case) */
- if (s->h_count[i] > s->h_max)
- s->h_max = s->h_count[i];
- if (s->v_count[i] > s->v_max)
- s->v_max = s->v_count[i];
+ if (h_count[i] > s->h_max)
+ s->h_max = h_count[i];
+ if (v_count[i] > s->v_max)
+ s->v_max = v_count[i];
s->quant_index[i] = get_bits(&s->gb, 8);
- if (s->quant_index[i] >= 4)
+ if (s->quant_index[i] >= 4) {
+ av_log(s->avctx, AV_LOG_ERROR, "quant_index is invalid\n");
return AVERROR_INVALIDDATA;
- if (!s->h_count[i] || !s->v_count[i]) {
+ }
+ if (!h_count[i] || !v_count[i]) {
av_log(s->avctx, AV_LOG_ERROR,
"Invalid sampling factor in component %d %d:%d\n",
- i, s->h_count[i], s->v_count[i]);
+ i, h_count[i], v_count[i]);
return AVERROR_INVALIDDATA;
}
av_log(s->avctx, AV_LOG_DEBUG, "component %d %d:%d id: %d quant:%d\n",
- i, s->h_count[i], s->v_count[i],
+ i, h_count[i], v_count[i],
s->component_id[i], s->quant_index[i]);
}
@@ -297,15 +334,18 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
return AVERROR_PATCHWELCOME;
}
- if (s->v_max == 1 && s->h_max == 1 && s->lossless == 1)
- s->rgb = 1;
/* if different size, realloc/alloc picture */
- /* XXX: also check h_count and v_count */
- if (width != s->width || height != s->height) {
+ if ( width != s->width || height != s->height
+ || memcmp(s->h_count, h_count, sizeof(h_count))
+ || memcmp(s->v_count, v_count, sizeof(v_count))) {
+
s->width = width;
s->height = height;
+ memcpy(s->h_count, h_count, sizeof(h_count));
+ memcpy(s->v_count, v_count, sizeof(v_count));
s->interlaced = 0;
+ s->got_picture = 0;
/* test interlaced mode */
if (s->first_picture &&
@@ -325,7 +365,16 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
s->first_picture = 0;
}
- if (!(s->interlaced && (s->bottom_field == !s->interlace_polarity))) {
+ if (s->got_picture && s->interlaced && (s->bottom_field == !s->interlace_polarity)) {
+ if (s->progressive) {
+ avpriv_request_sample(s->avctx, "progressively coded interlaced picture");
+ return AVERROR_INVALIDDATA;
+ }
+ } else{
+ if (s->v_max == 1 && s->h_max == 1 && s->lossless==1 && (nb_components==3 || nb_components==4))
+ s->rgb = 1;
+ else if (!s->lossless)
+ s->rgb = 0;
/* XXX: not complete test ! */
pix_fmt_id = (s->h_count[0] << 28) | (s->v_count[0] << 24) |
(s->h_count[1] << 20) | (s->v_count[1] << 16) |
@@ -339,38 +388,155 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
if (!(pix_fmt_id & 0x0D0D0D0D))
pix_fmt_id -= (pix_fmt_id & 0x0F0F0F0F) >> 1;
+ for (i = 0; i < 8; i++) {
+ int j = 6 + (i&1) - (i&6);
+ int is = (pix_fmt_id >> (4*i)) & 0xF;
+ int js = (pix_fmt_id >> (4*j)) & 0xF;
+
+ if (is == 1 && js != 2 && (i < 2 || i > 5))
+ js = (pix_fmt_id >> ( 8 + 4*(i&1))) & 0xF;
+ if (is == 1 && js != 2 && (i < 2 || i > 5))
+ js = (pix_fmt_id >> (16 + 4*(i&1))) & 0xF;
+
+ if (is == 1 && js == 2) {
+ if (i & 1) s->upscale_h |= 1 << (j/2);
+ else s->upscale_v |= 1 << (j/2);
+ }
+ }
+
switch (pix_fmt_id) {
case 0x11111100:
if (s->rgb)
- s->avctx->pix_fmt = AV_PIX_FMT_BGRA;
+ s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48;
+ else {
+ if (s->component_id[0] == 'Q' && s->component_id[1] == 'F' && s->component_id[2] == 'A') {
+ s->avctx->pix_fmt = s->bits <= 8 ? AV_PIX_FMT_GBRP : AV_PIX_FMT_GBRP16;
+ } else {
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
+ else s->avctx->pix_fmt = AV_PIX_FMT_YUV444P16;
+ s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ }
+ }
+ av_assert0(s->nb_components == 3);
+ break;
+ case 0x11111111:
+ if (s->rgb)
+ s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_ABGR : AV_PIX_FMT_RGBA64;
else {
- s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
+ if (s->adobe_transform == 0 && s->bits <= 8) {
+ s->avctx->pix_fmt = AV_PIX_FMT_GBRAP;
+ } else {
+ s->avctx->pix_fmt = s->bits <= 8 ? AV_PIX_FMT_YUVA444P : AV_PIX_FMT_YUVA444P16;
+ s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ }
+ }
+ av_assert0(s->nb_components == 4);
+ break;
+ case 0x22111122:
+ if (s->adobe_transform == 0 && s->bits <= 8) {
+ s->avctx->pix_fmt = AV_PIX_FMT_GBRAP;
+ s->upscale_v = 6;
+ s->upscale_h = 6;
+ s->chroma_height = s->height;
+ } else if (s->adobe_transform == 2 && s->bits <= 8) {
+ s->avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
+ s->upscale_v = 6;
+ s->upscale_h = 6;
+ s->chroma_height = s->height;
+ s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ } else {
+ if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
+ else s->avctx->pix_fmt = AV_PIX_FMT_YUVA420P16;
s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
}
- assert(s->nb_components == 3);
+ av_assert0(s->nb_components == 4);
+ break;
+ case 0x12121100:
+ case 0x22122100:
+ case 0x21211100:
+ case 0x22211200:
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
+ else
+ goto unk_pixfmt;
+ s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ s->chroma_height = s->height;
+ break;
+ case 0x22221100:
+ case 0x22112200:
+ case 0x11222200:
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV444P : AV_PIX_FMT_YUVJ444P;
+ else
+ goto unk_pixfmt;
+ s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ s->chroma_height = s->height / 2;
break;
case 0x11000000:
- s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+ case 0x13000000:
+ case 0x14000000:
+ case 0x31000000:
+ case 0x33000000:
+ case 0x34000000:
+ case 0x41000000:
+ case 0x43000000:
+ case 0x44000000:
+ if(s->bits <= 8)
+ s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+ else
+ s->avctx->pix_fmt = AV_PIX_FMT_GRAY16;
break;
case 0x12111100:
- s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV440P : AV_PIX_FMT_YUVJ440P;
+ case 0x22211100:
+ case 0x22112100:
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV440P : AV_PIX_FMT_YUVJ440P;
+ else
+ goto unk_pixfmt;
s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ s->chroma_height = s->height / 2;
break;
case 0x21111100:
- s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
+ else s->avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
+ s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ break;
+ case 0x22121100:
+ case 0x22111200:
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
+ else
+ goto unk_pixfmt;
s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
break;
case 0x22111100:
- s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUVJ420P;
+ case 0x42111100:
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUVJ420P;
+ else s->avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
+ s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+ if (pix_fmt_id == 0x42111100) {
+ s->upscale_h = 6;
+ s->chroma_height = s->height / 2;
+ }
+ break;
+ case 0x41111100:
+ if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV411P : AV_PIX_FMT_YUVJ411P;
+ else
+ goto unk_pixfmt;
s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
break;
default:
+unk_pixfmt:
av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id);
+ s->upscale_h = s->upscale_v = 0;
+ return AVERROR_PATCHWELCOME;
+ }
+ if ((s->upscale_h || s->upscale_v) && s->avctx->lowres) {
+ av_log(s->avctx, AV_LOG_ERROR, "lowres not supported for weird subsampling\n");
return AVERROR_PATCHWELCOME;
}
if (s->ls) {
+ s->upscale_h = s->upscale_v = 0;
if (s->nb_components > 1)
s->avctx->pix_fmt = AV_PIX_FMT_RGB24;
+ 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
@@ -384,15 +550,13 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
}
av_frame_unref(s->picture_ptr);
- if (ff_get_buffer(s->avctx, s->picture_ptr, AV_GET_BUFFER_FLAG_REF) < 0) {
- av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ 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 < 3; i++)
+ for (i = 0; i < 4; i++)
s->linesize[i] = s->picture_ptr->linesize[i] << s->interlaced;
av_dlog(s->avctx, "%d %d %d %d %d %d\n",
@@ -403,6 +567,11 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
av_log(s->avctx, AV_LOG_DEBUG, "decode_sof0: error, len(%d) mismatch\n", len);
}
+ if (s->rgb && !s->lossless && !s->ls) {
+ av_log(s->avctx, AV_LOG_ERROR, "Unsupported coding and pixel format combination\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
/* totally blank picture as progressive JPEG will only add details to it */
if (s->progressive) {
int bw = (width + s->h_max * 8 - 1) / (s->h_max * 8);
@@ -411,8 +580,10 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
int size = bw * bh * s->h_count[i] * s->v_count[i];
av_freep(&s->blocks[i]);
av_freep(&s->last_nnz[i]);
- s->blocks[i] = av_malloc(size * sizeof(**s->blocks));
- s->last_nnz[i] = av_mallocz(size * sizeof(**s->last_nnz));
+ s->blocks[i] = av_mallocz_array(size, sizeof(**s->blocks));
+ s->last_nnz[i] = av_mallocz_array(size, sizeof(**s->last_nnz));
+ if (!s->blocks[i] || !s->last_nnz[i])
+ return AVERROR(ENOMEM);
s->block_stride[i] = bw * s->h_count[i];
}
memset(s->coefs_finished, 0, sizeof(s->coefs_finished));
@@ -424,11 +595,11 @@ static inline int mjpeg_decode_dc(MJpegDecodeContext *s, int dc_index)
{
int code;
code = get_vlc2(&s->gb, s->vlcs[0][dc_index].table, 9, 2);
- if (code < 0) {
+ if (code < 0 || code > 16) {
av_log(s->avctx, AV_LOG_WARNING,
"mjpeg_decode_dc: bad vlc: %d:%d (%p)\n",
0, dc_index, &s->vlcs[0][dc_index]);
- return 0xffff;
+ return 0xfffff;
}
if (code)
@@ -445,7 +616,7 @@ static int decode_block(MJpegDecodeContext *s, int16_t *block, int component,
/* DC coef */
val = mjpeg_decode_dc(s, dc_index);
- if (val == 0xffff) {
+ if (val == 0xfffff) {
av_log(s->avctx, AV_LOG_ERROR, "error dc\n");
return AVERROR_INVALIDDATA;
}
@@ -493,7 +664,7 @@ static int decode_dc_progressive(MJpegDecodeContext *s, int16_t *block,
int val;
s->bdsp.clear_block(block);
val = mjpeg_decode_dc(s, dc_index);
- if (val == 0xffff) {
+ if (val == 0xfffff) {
av_log(s->avctx, AV_LOG_ERROR, "error dc\n");
return AVERROR_INVALIDDATA;
}
@@ -667,46 +838,101 @@ static int decode_block_refinement(MJpegDecodeContext *s, int16_t *block,
#undef REFINE_BIT
#undef ZERO_RUN
-static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor,
- int point_transform)
+static int handle_rstn(MJpegDecodeContext *s, int nb_components)
+{
+ int i;
+ int reset = 0;
+
+ if (s->restart_interval) {
+ s->restart_count--;
+ if(s->restart_count == 0 && s->avctx->codec_id == AV_CODEC_ID_THP){
+ align_get_bits(&s->gb);
+ for (i = 0; i < nb_components; i++) /* reset dc */
+ s->last_dc[i] = (4 << s->bits);
+ }
+
+ i = 8 + ((-get_bits_count(&s->gb)) & 7);
+ /* skip RSTn */
+ if (s->restart_count == 0) {
+ if( show_bits(&s->gb, i) == (1 << i) - 1
+ || show_bits(&s->gb, i) == 0xFF) {
+ int pos = get_bits_count(&s->gb);
+ align_get_bits(&s->gb);
+ while (get_bits_left(&s->gb) >= 8 && show_bits(&s->gb, 8) == 0xFF)
+ skip_bits(&s->gb, 8);
+ if (get_bits_left(&s->gb) >= 8 && (get_bits(&s->gb, 8) & 0xF8) == 0xD0) {
+ for (i = 0; i < nb_components; i++) /* reset dc */
+ s->last_dc[i] = (4 << s->bits);
+ reset = 1;
+ } else
+ skip_bits_long(&s->gb, pos - get_bits_count(&s->gb));
+ }
+ }
+ }
+ return reset;
+}
+
+static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform)
{
int i, mb_x, mb_y;
uint16_t (*buffer)[4];
- int left[3], top[3], topleft[3];
+ int left[4], top[4], topleft[4];
const int linesize = s->linesize[0];
- const int mask = (1 << s->bits) - 1;
+ const int mask = ((1 << s->bits) - 1) << point_transform;
+ int resync_mb_y = 0;
+ int resync_mb_x = 0;
+
+ if (s->nb_components != 3 && s->nb_components != 4)
+ return AVERROR_INVALIDDATA;
+ if (s->v_max != 1 || s->h_max != 1 || !s->lossless)
+ return AVERROR_INVALIDDATA;
+
+
+ s->restart_count = s->restart_interval;
av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size,
(unsigned)s->mb_width * 4 * sizeof(s->ljpeg_buffer[0][0]));
buffer = s->ljpeg_buffer;
- for (i = 0; i < 3; i++)
- buffer[0][i] = 1 << (s->bits + point_transform - 1);
+ for (i = 0; i < 4; i++)
+ buffer[0][i] = 1 << (s->bits - 1);
for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
- const int modified_predictor = mb_y ? predictor : 1;
uint8_t *ptr = s->picture_ptr->data[0] + (linesize * mb_y);
if (s->interlaced && s->bottom_field)
ptr += linesize >> 1;
- for (i = 0; i < 3; i++)
+ for (i = 0; i < 4; i++)
top[i] = left[i] = topleft[i] = buffer[0][i];
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
- if (s->restart_interval && !s->restart_count)
+ int modified_predictor = predictor;
+
+ if (s->restart_interval && !s->restart_count){
s->restart_count = s->restart_interval;
+ resync_mb_x = mb_x;
+ resync_mb_y = mb_y;
+ for(i=0; i<4; i++)
+ top[i] = left[i]= topleft[i]= 1 << (s->bits - 1);
+ }
+ if (mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x || !mb_x)
+ modified_predictor = 1;
- for (i = 0; i < 3; i++) {
- int pred;
+ for (i=0;i<nb_components;i++) {
+ int pred, dc;
topleft[i] = top[i];
top[i] = buffer[mb_x][i];
PREDICT(pred, topleft[i], top[i], left[i], modified_predictor);
+ dc = mjpeg_decode_dc(s, s->dc_index[i]);
+ if(dc == 0xFFFFF)
+ return -1;
+
left[i] = buffer[mb_x][i] =
- mask & (pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform));
+ mask & (pred + (dc << point_transform));
}
if (s->restart_interval && !--s->restart_count) {
@@ -714,24 +940,47 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor,
skip_bits(&s->gb, 16); /* skip RSTn */
}
}
-
- if (s->rct) {
+ if (s->nb_components == 4) {
+ for(i=0; i<nb_components; i++) {
+ int c= s->comp_index[i];
+ if (s->bits <= 8) {
+ for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
+ ptr[4*mb_x+3-c] = buffer[mb_x][i];
+ }
+ } else if(s->bits == 9) {
+ return AVERROR_PATCHWELCOME;
+ } else {
+ for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
+ ((uint16_t*)ptr)[4*mb_x+c] = buffer[mb_x][i];
+ }
+ }
+ }
+ } else if (s->rct) {
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
- ptr[4 * mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200) >> 2);
- ptr[4 * mb_x + 0] = buffer[mb_x][1] + ptr[4 * mb_x + 1];
- ptr[4 * mb_x + 2] = buffer[mb_x][2] + ptr[4 * mb_x + 1];
+ ptr[3*mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2] - 0x200) >> 2);
+ ptr[3*mb_x + 0] = buffer[mb_x][1] + ptr[3*mb_x + 1];
+ ptr[3*mb_x + 2] = buffer[mb_x][2] + ptr[3*mb_x + 1];
}
} else if (s->pegasus_rct) {
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
- ptr[4 * mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2]) >> 2);
- ptr[4 * mb_x + 0] = buffer[mb_x][1] + ptr[4 * mb_x + 1];
- ptr[4 * mb_x + 2] = buffer[mb_x][2] + ptr[4 * mb_x + 1];
+ ptr[3*mb_x + 1] = buffer[mb_x][0] - ((buffer[mb_x][1] + buffer[mb_x][2]) >> 2);
+ ptr[3*mb_x + 0] = buffer[mb_x][1] + ptr[3*mb_x + 1];
+ ptr[3*mb_x + 2] = buffer[mb_x][2] + ptr[3*mb_x + 1];
}
} else {
- for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
- ptr[4 * mb_x + 0] = buffer[mb_x][2];
- ptr[4 * mb_x + 1] = buffer[mb_x][1];
- ptr[4 * mb_x + 2] = buffer[mb_x][0];
+ for(i=0; i<nb_components; i++) {
+ int c= s->comp_index[i];
+ if (s->bits <= 8) {
+ for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
+ ptr[3*mb_x+2-c] = buffer[mb_x][i];
+ }
+ } else if(s->bits == 9) {
+ return AVERROR_PATCHWELCOME;
+ } else {
+ for(mb_x = 0; mb_x < s->mb_width; mb_x++) {
+ ((uint16_t*)ptr)[3*mb_x+2-c] = buffer[mb_x][i];
+ }
+ }
}
}
}
@@ -741,48 +990,88 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor,
static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor,
int point_transform, int nb_components)
{
- int i, mb_x, mb_y;
+ int i, mb_x, mb_y, mask;
+ int bits= (s->bits+7)&~7;
+ int resync_mb_y = 0;
+ int resync_mb_x = 0;
+
+ point_transform += bits - s->bits;
+ mask = ((1 << s->bits) - 1) << point_transform;
+
+ av_assert0(nb_components>=1 && nb_components<=4);
for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
- if (s->restart_interval && !s->restart_count)
+ if (s->restart_interval && !s->restart_count){
s->restart_count = s->restart_interval;
+ resync_mb_x = mb_x;
+ resync_mb_y = mb_y;
+ }
- if (mb_x == 0 || mb_y == 0 || s->interlaced) {
+ if(!mb_x || mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x || s->interlaced){
+ int toprow = mb_y == resync_mb_y || mb_y == resync_mb_y+1 && mb_x < resync_mb_x;
+ int leftcol = !mb_x || mb_y == resync_mb_y && mb_x == resync_mb_x;
for (i = 0; i < nb_components; i++) {
uint8_t *ptr;
+ uint16_t *ptr16;
int n, h, v, x, y, c, j, linesize;
- n = s->nb_blocks[i];
- c = s->comp_index[i];
- h = s->h_scount[i];
- v = s->v_scount[i];
- x = 0;
- y = 0;
- linesize = s->linesize[c];
-
- for (j = 0; j < n; j++) {
- int pred;
- // FIXME optimize this crap
- ptr = s->picture_ptr->data[c] +
- (linesize * (v * mb_y + y)) +
- (h * mb_x + x);
- if (y == 0 && mb_y == 0) {
- if (x == 0 && mb_x == 0)
- pred = 128 << point_transform;
- else
- pred = ptr[-1];
- } else {
- if (x == 0 && mb_x == 0)
- pred = ptr[-linesize];
- else
- PREDICT(pred, ptr[-linesize - 1],
- ptr[-linesize], ptr[-1], predictor);
- }
+ n = s->nb_blocks[i];
+ c = s->comp_index[i];
+ h = s->h_scount[i];
+ v = s->v_scount[i];
+ x = 0;
+ y = 0;
+ linesize= s->linesize[c];
+
+ if(bits>8) linesize /= 2;
+
+ for(j=0; j<n; j++) {
+ int pred, dc;
+
+ dc = mjpeg_decode_dc(s, s->dc_index[i]);
+ if(dc == 0xFFFFF)
+ return -1;
+ if(bits<=8){
+ ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap
+ if(y==0 && toprow){
+ if(x==0 && leftcol){
+ pred= 1 << (bits - 1);
+ }else{
+ pred= ptr[-1];
+ }
+ }else{
+ if(x==0 && leftcol){
+ pred= ptr[-linesize];
+ }else{
+ PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
+ }
+ }
if (s->interlaced && s->bottom_field)
ptr += linesize >> 1;
- *ptr = pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform);
+ pred &= mask;
+ *ptr= pred + (dc << point_transform);
+ }else{
+ ptr16 = (uint16_t*)(s->picture_ptr->data[c] + 2*(linesize * (v * mb_y + y)) + 2*(h * mb_x + x)); //FIXME optimize this crap
+ if(y==0 && toprow){
+ if(x==0 && leftcol){
+ pred= 1 << (bits - 1);
+ }else{
+ pred= ptr16[-1];
+ }
+ }else{
+ if(x==0 && leftcol){
+ pred= ptr16[-linesize];
+ }else{
+ PREDICT(pred, ptr16[-linesize-1], ptr16[-linesize], ptr16[-1], predictor);
+ }
+ }
+ if (s->interlaced && s->bottom_field)
+ ptr16 += linesize >> 1;
+ pred &= mask;
+ *ptr16= pred + (dc << point_transform);
+ }
if (++x == h) {
x = 0;
y++;
@@ -792,7 +1081,8 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor,
} else {
for (i = 0; i < nb_components; i++) {
uint8_t *ptr;
- int n, h, v, x, y, c, j, linesize;
+ uint16_t *ptr16;
+ int n, h, v, x, y, c, j, linesize, dc;
n = s->nb_blocks[i];
c = s->comp_index[i];
h = s->h_scount[i];
@@ -801,16 +1091,30 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor,
y = 0;
linesize = s->linesize[c];
+ if(bits>8) linesize /= 2;
+
for (j = 0; j < n; j++) {
int pred;
- // FIXME optimize this crap
- ptr = s->picture_ptr->data[c] +
+ dc = mjpeg_decode_dc(s, s->dc_index[i]);
+ if(dc == 0xFFFFF)
+ return -1;
+ if(bits<=8){
+ ptr = s->picture_ptr->data[c] +
(linesize * (v * mb_y + y)) +
- (h * mb_x + x);
- PREDICT(pred, ptr[-linesize - 1],
- ptr[-linesize], ptr[-1], predictor);
- *ptr = pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform);
+ (h * mb_x + x); //FIXME optimize this crap
+ PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor);
+
+ pred &= mask;
+ *ptr = pred + (dc << point_transform);
+ }else{
+ ptr16 = (uint16_t*)(s->picture_ptr->data[c] + 2*(linesize * (v * mb_y + y)) + 2*(h * mb_x + x)); //FIXME optimize this crap
+ PREDICT(pred, ptr16[-linesize-1], ptr16[-linesize], ptr16[-1], predictor);
+
+ pred &= mask;
+ *ptr16= pred + (dc << point_transform);
+ }
+
if (++x == h) {
x = 0;
y++;
@@ -827,18 +1131,58 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor,
return 0;
}
+static av_always_inline void mjpeg_copy_block(MJpegDecodeContext *s,
+ uint8_t *dst, const uint8_t *src,
+ int linesize, int lowres)
+{
+ switch (lowres) {
+ case 0: s->hdsp.put_pixels_tab[1][0](dst, src, linesize, 8);
+ break;
+ case 1: copy_block4(dst, src, linesize, linesize, 4);
+ break;
+ case 2: copy_block2(dst, src, linesize, linesize, 2);
+ break;
+ case 3: *dst = *src;
+ break;
+ }
+}
+
+static void shift_output(MJpegDecodeContext *s, uint8_t *ptr, int linesize)
+{
+ int block_x, block_y;
+ int size = 8 >> s->avctx->lowres;
+ if (s->bits > 8) {
+ for (block_y=0; block_y<size; block_y++)
+ for (block_x=0; block_x<size; block_x++)
+ *(uint16_t*)(ptr + 2*block_x + block_y*linesize) <<= 16 - s->bits;
+ } else {
+ for (block_y=0; block_y<size; block_y++)
+ for (block_x=0; block_x<size; block_x++)
+ *(ptr + block_x + block_y*linesize) <<= 8 - s->bits;
+ }
+}
+
static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
int Al, const uint8_t *mb_bitmask,
+ int mb_bitmask_size,
const AVFrame *reference)
{
int i, mb_x, mb_y;
uint8_t *data[MAX_COMPONENTS];
const uint8_t *reference_data[MAX_COMPONENTS];
int linesize[MAX_COMPONENTS];
- GetBitContext mb_bitmask_gb;
+ GetBitContext mb_bitmask_gb = {0}; // initialize to silence gcc warning
+ int bytes_per_pixel = 1 + (s->bits > 8);
- if (mb_bitmask)
+ if (mb_bitmask) {
+ if (mb_bitmask_size != (s->mb_width * s->mb_height + 7)>>3) {
+ av_log(s->avctx, AV_LOG_ERROR, "mb_bitmask_size mismatches\n");
+ return AVERROR_INVALIDDATA;
+ }
init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height);
+ }
+
+ s->restart_count = 0;
for (i = 0; i < nb_components; i++) {
int c = s->comp_index[i];
@@ -871,27 +1215,29 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
x = 0;
y = 0;
for (j = 0; j < n; j++) {
- block_offset = ((linesize[c] * (v * mb_y + y) * 8) +
- (h * mb_x + x) * 8);
+ block_offset = (((linesize[c] * (v * mb_y + y) * 8) +
+ (h * mb_x + x) * 8 * bytes_per_pixel) >> s->avctx->lowres);
if (s->interlaced && s->bottom_field)
block_offset += linesize[c] >> 1;
ptr = data[c] + block_offset;
if (!s->progressive) {
if (copy_mb)
- s->hdsp.put_pixels_tab[1][0](ptr,
- reference_data[c] + block_offset,
- linesize[c], 8);
+ mjpeg_copy_block(s, ptr, reference_data[c] + block_offset,
+ linesize[c], s->avctx->lowres);
+
else {
s->bdsp.clear_block(s->block);
if (decode_block(s, s->block, i,
s->dc_index[i], s->ac_index[i],
- s->quant_matrixes[s->quant_index[c]]) < 0) {
+ s->quant_matrixes[s->quant_sindex[i]]) < 0) {
av_log(s->avctx, AV_LOG_ERROR,
"error y=%d x=%d\n", mb_y, mb_x);
return AVERROR_INVALIDDATA;
}
s->idsp.idct_put(ptr, linesize[c], s->block);
+ if (s->bits & 7)
+ shift_output(s, ptr, linesize[c]);
}
} else {
int block_idx = s->block_stride[c] * (v * mb_y + y) +
@@ -899,9 +1245,9 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
int16_t *block = s->blocks[c][block_idx];
if (Ah)
block[0] += get_bits1(&s->gb) *
- s->quant_matrixes[s->quant_index[c]][0] << Al;
+ s->quant_matrixes[s->quant_sindex[i]][0] << Al;
else if (decode_dc_progressive(s, block, i, s->dc_index[i],
- s->quant_matrixes[s->quant_index[c]],
+ s->quant_matrixes[s->quant_sindex[i]],
Al) < 0) {
av_log(s->avctx, AV_LOG_ERROR,
"error y=%d x=%d\n", mb_y, mb_x);
@@ -919,72 +1265,50 @@ static int mjpeg_decode_scan(MJpegDecodeContext *s, int nb_components, int Ah,
}
}
- if (s->restart_interval) {
- s->restart_count--;
- i = 8 + ((-get_bits_count(&s->gb)) & 7);
- /* skip RSTn */
- if (show_bits(&s->gb, i) == (1 << i) - 1) {
- int pos = get_bits_count(&s->gb);
- align_get_bits(&s->gb);
- while (get_bits_left(&s->gb) >= 8 && show_bits(&s->gb, 8) == 0xFF)
- skip_bits(&s->gb, 8);
- if ((get_bits(&s->gb, 8) & 0xF8) == 0xD0) {
- for (i = 0; i < nb_components; i++) /* reset dc */
- s->last_dc[i] = 1024;
- } else
- skip_bits_long(&s->gb, pos - get_bits_count(&s->gb));
- }
- }
+ handle_rstn(s, nb_components);
}
}
return 0;
}
static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss,
- int se, int Ah, int Al,
- const uint8_t *mb_bitmask,
- const AVFrame *reference)
+ int se, int Ah, int Al)
{
int mb_x, mb_y;
int EOBRUN = 0;
int c = s->comp_index[0];
uint8_t *data = s->picture_ptr->data[c];
- const uint8_t *reference_data = reference ? reference->data[c] : NULL;
int linesize = s->linesize[c];
int last_scan = 0;
- int16_t *quant_matrix = s->quant_matrixes[s->quant_index[c]];
- GetBitContext mb_bitmask_gb;
+ int16_t *quant_matrix = s->quant_matrixes[s->quant_sindex[0]];
+ int bytes_per_pixel = 1 + (s->bits > 8);
- if (ss < 0 || ss >= 64 ||
- se < ss || se >= 64 ||
- Ah < 0 || Al < 0)
+ av_assert0(ss>=0 && Ah>=0 && Al>=0);
+ if (se < ss || se > 63) {
+ av_log(s->avctx, AV_LOG_ERROR, "SS/SE %d/%d is invalid\n", ss, se);
return AVERROR_INVALIDDATA;
-
- if (mb_bitmask)
- init_get_bits(&mb_bitmask_gb, mb_bitmask, s->mb_width * s->mb_height);
+ }
if (!Al) {
- s->coefs_finished[c] |= (1LL << (se + 1)) - (1LL << ss);
+ s->coefs_finished[c] |= (2ULL << se) - (1ULL << ss);
last_scan = !~s->coefs_finished[c];
}
- if (s->interlaced && s->bottom_field) {
- int offset = linesize >> 1;
- data += offset;
- reference_data += offset;
- }
+ if (s->interlaced && s->bottom_field)
+ data += linesize >> 1;
+
+ s->restart_count = 0;
for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
- int block_offset = mb_y * linesize * 8;
- uint8_t *ptr = data + block_offset;
+ uint8_t *ptr = data + (mb_y * linesize * 8 >> s->avctx->lowres);
int block_idx = mb_y * s->block_stride[c];
int16_t (*block)[64] = &s->blocks[c][block_idx];
uint8_t *last_nnz = &s->last_nnz[c][block_idx];
for (mb_x = 0; mb_x < s->mb_width; mb_x++, block++, last_nnz++) {
- const int copy_mb = mb_bitmask && !get_bits1(&mb_bitmask_gb);
-
- if (!copy_mb) {
int ret;
+ if (s->restart_interval && !s->restart_count)
+ s->restart_count = s->restart_interval;
+
if (Ah)
ret = decode_block_refinement(s, *block, last_nnz, s->ac_index[0],
quant_matrix, ss, se, Al, &EOBRUN);
@@ -996,31 +1320,35 @@ static int mjpeg_decode_scan_progressive_ac(MJpegDecodeContext *s, int ss,
"error y=%d x=%d\n", mb_y, mb_x);
return AVERROR_INVALIDDATA;
}
- }
if (last_scan) {
- if (copy_mb) {
- s->hdsp.put_pixels_tab[1][0](ptr,
- reference_data + block_offset,
- linesize, 8);
- } else {
s->idsp.idct_put(ptr, linesize, *block);
- ptr += 8;
- }
+ if (s->bits & 7)
+ shift_output(s, ptr, linesize);
+ ptr += bytes_per_pixel*8 >> s->avctx->lowres;
}
+ if (handle_rstn(s, 0))
+ EOBRUN = 0;
}
}
return 0;
}
int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,
- const AVFrame *reference)
+ int mb_bitmask_size, const AVFrame *reference)
{
int len, nb_components, i, h, v, predictor, point_transform;
int index, id, ret;
const int block_size = s->lossless ? 1 : 8;
int ilv, prev_shift;
+ if (!s->got_picture) {
+ av_log(s->avctx, AV_LOG_WARNING,
+ "Can not process SOS before SOF, skipping\n");
+ return -1;
+ }
+
+ av_assert0(s->picture_ptr->data[0]);
/* XXX: verify len field validity */
len = get_bits(&s->gb, 16);
nb_components = get_bits(&s->gb, 8);
@@ -1050,27 +1378,35 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,
&& nb_components == 3 && s->nb_components == 3 && i)
index = 3 - i;
- s->comp_index[i] = index;
-
+ s->quant_sindex[i] = s->quant_index[index];
s->nb_blocks[i] = s->h_count[index] * s->v_count[index];
s->h_scount[i] = s->h_count[index];
s->v_scount[i] = s->v_count[index];
+ if(nb_components == 3 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P)
+ index = (i+2)%3;
+ if(nb_components == 1 && s->nb_components == 3 && s->avctx->pix_fmt == AV_PIX_FMT_GBR24P)
+ index = (index+2)%3;
+
+ s->comp_index[i] = index;
+
s->dc_index[i] = get_bits(&s->gb, 4);
s->ac_index[i] = get_bits(&s->gb, 4);
if (s->dc_index[i] < 0 || s->ac_index[i] < 0 ||
s->dc_index[i] >= 4 || s->ac_index[i] >= 4)
goto out_of_range;
- if (!s->vlcs[0][s->dc_index[i]].table ||
- !s->vlcs[1][s->ac_index[i]].table)
+ if (!s->vlcs[0][s->dc_index[i]].table || !(s->progressive ? s->vlcs[2][s->ac_index[0]].table : s->vlcs[1][s->ac_index[i]].table))
goto out_of_range;
}
predictor = get_bits(&s->gb, 8); /* JPEG Ss / lossless JPEG predictor /JPEG-LS NEAR */
ilv = get_bits(&s->gb, 8); /* JPEG Se / JPEG-LS ILV */
- prev_shift = get_bits(&s->gb, 4); /* Ah */
- point_transform = get_bits(&s->gb, 4); /* Al */
+ if(s->avctx->codec_tag != AV_RL32("CJPG")){
+ prev_shift = get_bits(&s->gb, 4); /* Ah */
+ point_transform = get_bits(&s->gb, 4); /* Al */
+ }else
+ prev_shift = point_transform = 0;
if (nb_components > 1) {
/* interleaved stream */
@@ -1087,10 +1423,10 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,
}
if (s->avctx->debug & FF_DEBUG_PICT_INFO)
- av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d %s\n",
+ av_log(s->avctx, AV_LOG_DEBUG, "%s %s p:%d >>:%d ilv:%d bits:%d skip:%d %s comp:%d\n",
s->lossless ? "lossless" : "sequential DCT", s->rgb ? "RGB" : "",
- predictor, point_transform, ilv, s->bits,
- s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""));
+ predictor, point_transform, ilv, s->bits, s->mjpb_skiptosod,
+ s->pegasus_rct ? "PRCT" : (s->rct ? "RCT" : ""), nb_components);
/* mjpeg-b can have padding bytes between sos and image data, skip them */
@@ -1099,9 +1435,10 @@ int ff_mjpeg_decode_sos(MJpegDecodeContext *s, const uint8_t *mb_bitmask,
next_field:
for (i = 0; i < nb_components; i++)
- s->last_dc[i] = 1024;
+ s->last_dc[i] = (4 << s->bits);
if (s->lossless) {
+ av_assert0(s->picture_ptr == s->picture);
if (CONFIG_JPEGLS_DECODER && s->ls) {
// for () {
// reset_ls_coding_parameters(s, 0);
@@ -1111,8 +1448,7 @@ next_field:
return ret;
} else {
if (s->rgb) {
- if ((ret = ljpeg_decode_rgb_scan(s, predictor,
- point_transform)) < 0)
+ if ((ret = ljpeg_decode_rgb_scan(s, nb_components, predictor, point_transform)) < 0)
return ret;
} else {
if ((ret = ljpeg_decode_yuv_scan(s, predictor,
@@ -1123,16 +1459,15 @@ next_field:
}
} else {
if (s->progressive && predictor) {
+ av_assert0(s->picture_ptr == s->picture);
if ((ret = mjpeg_decode_scan_progressive_ac(s, predictor,
ilv, prev_shift,
- point_transform,
- mb_bitmask,
- reference)) < 0)
+ point_transform)) < 0)
return ret;
} else {
if ((ret = mjpeg_decode_scan(s, nb_components,
prev_shift, point_transform,
- mb_bitmask, reference)) < 0)
+ mb_bitmask, mb_bitmask_size, reference)) < 0)
return ret;
}
}
@@ -1143,7 +1478,7 @@ next_field:
GetBitContext bak = s->gb;
align_get_bits(&bak);
if (show_bits(&bak, 16) == 0xFFD1) {
- av_dlog(s->avctx, "AVRn interlaced picture marker found\n");
+ av_log(s->avctx, AV_LOG_DEBUG, "AVRn interlaced picture marker found\n");
s->gb = bak;
skip_bits(&s->gb, 16);
s->bottom_field ^= 1;
@@ -1176,22 +1511,24 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
int len, id, i;
len = get_bits(&s->gb, 16);
- if (len < 5)
+ if (len < 6)
return AVERROR_INVALIDDATA;
if (8 * len > get_bits_left(&s->gb))
return AVERROR_INVALIDDATA;
id = get_bits_long(&s->gb, 32);
- id = av_be2ne32(id);
len -= 6;
- if (s->avctx->debug & FF_DEBUG_STARTCODE)
- av_log(s->avctx, AV_LOG_DEBUG, "APPx %8X\n", id);
+ 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_RL32("AVI1")) {
+ if (id == AV_RB32("AVI1")) {
/* structure:
4bytes AVI1
1bytes polarity
@@ -1199,12 +1536,9 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
4bytes field_size
4bytes field_size_less_padding
*/
- s->buggy_avid = 1;
- i = get_bits(&s->gb, 8);
- if (i == 2)
- s->bottom_field = 1;
- else if (i == 1)
- s->bottom_field = 0;
+ 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);
@@ -1216,7 +1550,7 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
// len -= 2;
- if (id == AV_RL32("JFIF")) {
+ 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);
@@ -1245,26 +1579,26 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
goto out;
}
- if (id == AV_RL32("Adob") && (get_bits(&s->gb, 8) == 'e')) {
- if (s->avctx->debug & FF_DEBUG_PICT_INFO)
- av_log(s->avctx, AV_LOG_INFO, "mjpeg: Adobe header found\n");
+ if (id == AV_RB32("Adob") && (get_bits(&s->gb, 8) == 'e')) {
skip_bits(&s->gb, 16); /* version */
skip_bits(&s->gb, 16); /* flags0 */
skip_bits(&s->gb, 16); /* flags1 */
- skip_bits(&s->gb, 8); /* transform */
+ 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;
goto out;
}
- if (id == AV_RL32("LJIF")) {
+ if (id == AV_RB32("LJIF")) {
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); /* unknwon always 0? */
- skip_bits(&s->gb, 16); /* unknwon always 0? */
- skip_bits(&s->gb, 16); /* unknwon always 0? */
- switch (get_bits(&s->gb, 8)) {
+ 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:
s->rgb = 1;
s->pegasus_rct = 0;
@@ -1274,19 +1608,106 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
s->pegasus_rct = 1;
break;
default:
- av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace\n");
+ av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace %d\n", i);
}
len -= 9;
goto out;
}
+ 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 --;
+ goto out;
+ }
+ 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 --;
+ goto out;
+ }
+
+ /* 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) {
+ goto out;
+ }
+ 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;
+ }
+ }
+ goto out;
+ }
+
+ /* 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;
+
+ goto out;
+ }
/* Apple MJPEG-A */
if ((s->start_code == APP1) && (len > (0x28 - 8))) {
id = get_bits_long(&s->gb, 32);
- id = av_be2ne32(id);
len -= 4;
/* Apple MJPEG-A */
- if (id == AV_RL32("mjpg")) {
+ if (id == AV_RB32("mjpg")) {
#if 0
skip_bits(&s->gb, 32); /* field size */
skip_bits(&s->gb, 32); /* pad field size */
@@ -1328,15 +1749,15 @@ static int mjpeg_decode_com(MJpegDecodeContext *s)
cbuf[i] = 0;
if (s->avctx->debug & FF_DEBUG_PICT_INFO)
- av_log(s->avctx, AV_LOG_INFO, "mjpeg comment: '%s'\n", cbuf);
+ av_log(s->avctx, AV_LOG_INFO, "comment: '%s'\n", cbuf);
/* buggy avid, it puts EOI only at every 10th frame */
- if (!strcmp(cbuf, "AVID")) {
- s->buggy_avid = 1;
+ if (!strncmp(cbuf, "AVID", 4)) {
+ parse_avid(s, cbuf, len);
} else if (!strcmp(cbuf, "CS=ITU601"))
s->cs_itu601 = 1;
- else if ((len > 20 && !strncmp(cbuf, "Intel(R) JPEG Library", 21)) ||
- (len > 19 && !strncmp(cbuf, "Metasoft MJPEG Codec", 20)))
+ else if ((!strncmp(cbuf, "Intel(R) JPEG Library, version 1", 32) && s->avctx->codec_tag) ||
+ (!strncmp(cbuf, "Metasoft MJPEG Codec", 20)))
s->flipped = 1;
av_free(cbuf);
@@ -1353,22 +1774,19 @@ static int find_marker(const uint8_t **pbuf_ptr, const uint8_t *buf_end)
const uint8_t *buf_ptr;
unsigned int v, v2;
int val;
-#ifdef DEBUG
int skipped = 0;
-#endif
buf_ptr = *pbuf_ptr;
- while (buf_ptr < buf_end) {
+ while (buf_end - buf_ptr > 1) {
v = *buf_ptr++;
v2 = *buf_ptr;
if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) {
val = *buf_ptr++;
goto found;
}
-#ifdef DEBUG
skipped++;
-#endif
}
+ buf_ptr = buf_end;
val = -1;
found:
av_dlog(NULL, "find_marker skipped %d bytes\n", skipped);
@@ -1414,7 +1832,7 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s,
memset(s->buffer + *unescaped_buf_size, 0,
FF_INPUT_BUFFER_PADDING_SIZE);
- av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n",
+ av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %"PTRDIFF_SPECIFIER" bytes\n",
(buf_end - *buf_ptr) - (dst - s->buffer));
} else if (start_code == SOS && s->ls) {
const uint8_t *src = *buf_ptr;
@@ -1423,8 +1841,6 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s,
int t = 0, b = 0;
PutBitContext pb;
- s->cur_scan++;
-
/* find marker */
while (src + t < buf_end) {
uint8_t x = src[t++];
@@ -1432,7 +1848,7 @@ int ff_mjpeg_find_marker(MJpegDecodeContext *s,
while ((src + t < buf_end) && x == 0xff)
x = src[t++];
if (x & 0x80) {
- t -= 2;
+ t -= FFMIN(2, t);
break;
}
}
@@ -1473,11 +1889,16 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
MJpegDecodeContext *s = avctx->priv_data;
const uint8_t *buf_end, *buf_ptr;
const uint8_t *unescaped_buf_ptr;
+ int hshift, vshift;
int unescaped_buf_size;
int start_code;
+ int i, index;
int ret = 0;
- s->got_picture = 0; // picture from previous image can not be reused
+ av_dict_free(&s->exif_metadata);
+ av_freep(&s->stereo3d);
+ s->adobe_transform = -1;
+
buf_ptr = buf;
buf_end = buf + buf_size;
while (buf_ptr < buf_end) {
@@ -1487,21 +1908,22 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
&unescaped_buf_size);
/* EOF */
if (start_code < 0) {
- goto the_end;
+ break;
} 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);
return AVERROR_INVALIDDATA;
}
-
- av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n",
+ av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%"PTRDIFF_SPECIFIER"\n",
start_code, buf_end - buf_ptr);
- ret = init_get_bits(&s->gb, unescaped_buf_ptr,
- unescaped_buf_size * 8);
- if (ret < 0)
- return ret;
+ ret = init_get_bits8(&s->gb, unescaped_buf_ptr, unescaped_buf_size);
+
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "invalid buffer\n");
+ goto fail;
+ }
s->start_code = start_code;
if (s->avctx->debug & FF_DEBUG_STARTCODE)
@@ -1518,6 +1940,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
else if (start_code == COM)
mjpeg_decode_com(s);
+ ret = -1;
+
if (!CONFIG_JPEGLS_DECODER &&
(start_code == SOF48 || start_code == LSE)) {
av_log(avctx, AV_LOG_ERROR, "JPEG-LS support not enabled.\n");
@@ -1536,7 +1960,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
case DHT:
if ((ret = ff_mjpeg_decode_dht(s)) < 0) {
av_log(avctx, AV_LOG_ERROR, "huffman table decode error\n");
- return ret;
+ goto fail;
}
break;
case SOF0:
@@ -1545,39 +1969,37 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
s->ls = 0;
s->progressive = 0;
if ((ret = ff_mjpeg_decode_sof(s)) < 0)
- return ret;
+ goto fail;
break;
case SOF2:
s->lossless = 0;
s->ls = 0;
s->progressive = 1;
if ((ret = ff_mjpeg_decode_sof(s)) < 0)
- return ret;
+ goto fail;
break;
case SOF3:
s->lossless = 1;
s->ls = 0;
s->progressive = 0;
if ((ret = ff_mjpeg_decode_sof(s)) < 0)
- return ret;
+ goto fail;
break;
case SOF48:
s->lossless = 1;
s->ls = 1;
s->progressive = 0;
if ((ret = ff_mjpeg_decode_sof(s)) < 0)
- return ret;
+ goto fail;
break;
case LSE:
if (!CONFIG_JPEGLS_DECODER ||
(ret = ff_jpegls_decode_lse(s)) < 0)
- return ret;
+ goto fail;
break;
case EOI:
- s->cur_scan = 0;
- if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
- break;
eoi_parser:
+ s->cur_scan = 0;
if (!s->got_picture) {
av_log(avctx, AV_LOG_WARNING,
"Found EOI before any SOF, ignoring\n");
@@ -1587,43 +2009,34 @@ eoi_parser:
s->bottom_field ^= 1;
/* if not bottom field, do not output image yet */
if (s->bottom_field == !s->interlace_polarity)
- goto not_the_end;
+ break;
}
if ((ret = av_frame_ref(frame, s->picture_ptr)) < 0)
return ret;
- if (s->flipped) {
- int i;
- for (i = 0; frame->data[i]; i++) {
- int h = frame->height >> ((i == 1 || i == 2) ?
- s->pix_desc->log2_chroma_h : 0);
- frame->data[i] += frame->linesize[i] * (h - 1);
- frame->linesize[i] *= -1;
- }
- }
*got_frame = 1;
+ s->got_picture = 0;
+
+ if (!s->lossless) {
+ 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 (!s->lossless &&
- avctx->debug & FF_DEBUG_QP) {
- av_log(avctx, AV_LOG_DEBUG,
- "QP: %d\n", FFMAX3(s->qscale[0],
- s->qscale[1],
- s->qscale[2]));
+ if(avctx->debug & FF_DEBUG_QP)
+ av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", qp);
}
goto the_end;
case SOS:
- if (!s->got_picture) {
- av_log(avctx, AV_LOG_WARNING,
- "Can not process SOS before SOF, skipping\n");
- break;
- }
- if ((ret = ff_mjpeg_decode_sos(s, NULL, NULL)) < 0 &&
+ s->cur_scan++;
+ if ((ret = ff_mjpeg_decode_sos(s, NULL, 0, NULL)) < 0 &&
(avctx->err_recognition & AV_EF_EXPLODE))
- return ret;
- /* buggy avid puts EOI every 10-20th frame */
- /* if restart period is over process EOI */
- if ((s->buggy_avid && !s->interlaced) || s->restart_interval)
- goto eoi_parser;
+ goto fail;
break;
case DRI:
mjpeg_decode_dri(s);
@@ -1643,21 +2056,158 @@ eoi_parser:
break;
}
-not_the_end:
/* eof process start code */
buf_ptr += (get_bits_count(&s->gb) + 7) / 8;
av_log(avctx, AV_LOG_DEBUG,
"marker parser used %d bytes (%d bits)\n",
(get_bits_count(&s->gb) + 7) / 8, get_bits_count(&s->gb));
}
- if (s->got_picture) {
+ if (s->got_picture && s->cur_scan) {
av_log(avctx, AV_LOG_WARNING, "EOI missing, emulating\n");
goto eoi_parser;
}
av_log(avctx, AV_LOG_FATAL, "No JPEG data found in image\n");
return AVERROR_INVALIDDATA;
+fail:
+ s->got_picture = 0;
+ return ret;
the_end:
- av_log(avctx, AV_LOG_DEBUG, "mjpeg decode frame unused %td bytes\n",
+ if (s->upscale_h) {
+ int p;
+ av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUV444P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUVJ440P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUV440P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUVA444P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUVJ420P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUV420P ||
+ avctx->pix_fmt == AV_PIX_FMT_GBRAP
+ );
+ avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
+ for (p = 0; p<4; p++) {
+ uint8_t *line = s->picture_ptr->data[p];
+ int w = s->width;
+ if (!(s->upscale_h & (1<<p)))
+ continue;
+ if (p==1 || p==2)
+ w >>= hshift;
+ for (i = 0; i < s->chroma_height; i++) {
+ for (index = w - 1; index; index--)
+ line[index] = (line[index / 2] + line[(index + 1) / 2]) >> 1;
+ line += s->linesize[p];
+ }
+ }
+ }
+ if (s->upscale_v) {
+ int p;
+ av_assert0(avctx->pix_fmt == AV_PIX_FMT_YUVJ444P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUV444P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUVJ422P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUV422P ||
+ avctx->pix_fmt == AV_PIX_FMT_YUVA444P ||
+ avctx->pix_fmt == AV_PIX_FMT_GBRAP
+ );
+ avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
+ for (p = 0; p < 4; p++) {
+ uint8_t *dst = &((uint8_t *)s->picture_ptr->data[p])[(s->height - 1) * s->linesize[p]];
+ int w = s->width;
+ if (!(s->upscale_v & (1<<p)))
+ continue;
+ if (p==1 || p==2)
+ w >>= hshift;
+ for (i = s->height - 1; i; i--) {
+ uint8_t *src1 = &((uint8_t *)s->picture_ptr->data[p])[i / 2 * s->linesize[p]];
+ uint8_t *src2 = &((uint8_t *)s->picture_ptr->data[p])[(i + 1) / 2 * s->linesize[p]];
+ if (src1 == src2) {
+ memcpy(dst, src1, w);
+ } else {
+ for (index = 0; index < w; index++)
+ dst[index] = (src1[index] + src2[index]) >> 1;
+ }
+ dst -= s->linesize[p];
+ }
+ }
+ }
+ if (s->flipped) {
+ int j;
+ avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
+ for (index=0; index<4; index++) {
+ uint8_t *dst = s->picture_ptr->data[index];
+ int w = s->picture_ptr->width;
+ int h = s->picture_ptr->height;
+ if(index && index<3){
+ w = FF_CEIL_RSHIFT(w, hshift);
+ h = FF_CEIL_RSHIFT(h, vshift);
+ }
+ if(dst){
+ uint8_t *dst2 = dst + s->picture_ptr->linesize[index]*(h-1);
+ for (i=0; i<h/2; i++) {
+ for (j=0; j<w; j++)
+ FFSWAP(int, dst[j], dst2[j]);
+ dst += s->picture_ptr->linesize[index];
+ dst2 -= s->picture_ptr->linesize[index];
+ }
+ }
+ }
+ }
+ if (s->adobe_transform == 0 && s->avctx->pix_fmt == AV_PIX_FMT_GBRAP) {
+ int w = s->picture_ptr->width;
+ int h = s->picture_ptr->height;
+ for (i=0; i<h; i++) {
+ int j;
+ uint8_t *dst[4];
+ for (index=0; index<4; index++) {
+ dst[index] = s->picture_ptr->data[index]
+ + s->picture_ptr->linesize[index]*i;
+ }
+ for (j=0; j<w; j++) {
+ int k = dst[3][j];
+ int r = dst[0][j] * k;
+ int g = dst[1][j] * k;
+ int b = dst[2][j] * k;
+ dst[0][j] = g*257 >> 16;
+ dst[1][j] = b*257 >> 16;
+ dst[2][j] = r*257 >> 16;
+ dst[3][j] = 255;
+ }
+ }
+ }
+ if (s->adobe_transform == 2 && s->avctx->pix_fmt == AV_PIX_FMT_YUVA444P) {
+ int w = s->picture_ptr->width;
+ int h = s->picture_ptr->height;
+ for (i=0; i<h; i++) {
+ int j;
+ uint8_t *dst[4];
+ for (index=0; index<4; index++) {
+ dst[index] = s->picture_ptr->data[index]
+ + s->picture_ptr->linesize[index]*i;
+ }
+ for (j=0; j<w; j++) {
+ int k = dst[3][j];
+ int r = (255 - dst[0][j]) * k;
+ int g = (128 - dst[1][j]) * k;
+ int b = (128 - dst[2][j]) * k;
+ dst[0][j] = r*257 >> 16;
+ dst[1][j] = (g*257 >> 16) + 128;
+ dst[2][j] = (b*257 >> 16) + 128;
+ dst[3][j] = 255;
+ }
+ }
+ }
+
+ if (s->stereo3d) {
+ AVStereo3D *stereo = av_stereo3d_create_side_data(data);
+ if (stereo) {
+ stereo->type = s->stereo3d->type;
+ stereo->flags = s->stereo3d->flags;
+ }
+ av_freep(&s->stereo3d);
+ }
+
+ av_dict_copy(avpriv_frame_get_metadatap(data), s->exif_metadata, 0);
+ av_dict_free(&s->exif_metadata);
+
+ 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;
@@ -1668,13 +2218,18 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
MJpegDecodeContext *s = avctx->priv_data;
int i, j;
+ if (s->interlaced && s->bottom_field == !s->interlace_polarity && s->got_picture && !avctx->frame_number) {
+ av_log(avctx, AV_LOG_INFO, "Single field\n");
+ }
+
if (s->picture) {
av_frame_free(&s->picture);
s->picture_ptr = NULL;
} else if (s->picture_ptr)
av_frame_unref(s->picture_ptr);
- av_free(s->buffer);
+ av_freep(&s->buffer);
+ av_freep(&s->stereo3d);
av_freep(&s->ljpeg_buffer);
s->ljpeg_buffer_size = 0;
@@ -1686,9 +2241,17 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx)
av_freep(&s->blocks[i]);
av_freep(&s->last_nnz[i]);
}
+ av_dict_free(&s->exif_metadata);
return 0;
}
+static void decode_flush(AVCodecContext *avctx)
+{
+ MJpegDecodeContext *s = avctx->priv_data;
+ s->got_picture = 0;
+}
+
+#if CONFIG_MJPEG_DECODER
#define OFFSET(x) offsetof(MJpegDecodeContext, x)
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
@@ -1713,10 +2276,13 @@ AVCodec ff_mjpeg_decoder = {
.init = ff_mjpeg_decode_init,
.close = ff_mjpeg_decode_end,
.decode = ff_mjpeg_decode_frame,
+ .flush = decode_flush,
.capabilities = CODEC_CAP_DR1,
+ .max_lowres = 3,
.priv_class = &mjpegdec_class,
};
-
+#endif
+#if CONFIG_THP_DECODER
AVCodec ff_thp_decoder = {
.name = "thp",
.long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"),
@@ -1726,5 +2292,8 @@ AVCodec ff_thp_decoder = {
.init = ff_mjpeg_decode_init,
.close = ff_mjpeg_decode_end,
.decode = ff_mjpeg_decode_frame,
+ .flush = decode_flush,
.capabilities = CODEC_CAP_DR1,
+ .max_lowres = 3,
};
+#endif