+static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame,
+ int tile_byte_count, int dst_x, int dst_y, int w, int h)
+{
+ TiffContext *s = avctx->priv_data;
+ uint8_t *dst_data, *src_data;
+ uint32_t dst_offset; /* offset from dst buffer in pixels */
+ int is_single_comp, is_u16, pixel_size;
+ int ret;
+
+ if (tile_byte_count < 0 || tile_byte_count > bytestream2_get_bytes_left(&s->gb))
+ return AVERROR_INVALIDDATA;
+
+ /* Prepare a packet and send to the MJPEG decoder */
+ av_packet_unref(s->jpkt);
+ s->jpkt->data = (uint8_t*)s->gb.buffer;
+ s->jpkt->size = tile_byte_count;
+
+ if (s->is_bayer) {
+ MJpegDecodeContext *mjpegdecctx = s->avctx_mjpeg->priv_data;
+ /* We have to set this information here, there is no way to know if a given JPEG is a DNG-embedded
+ image or not from its own data (and we need that information when decoding it). */
+ mjpegdecctx->bayer = 1;
+ }
+
+ ret = avcodec_send_packet(s->avctx_mjpeg, s->jpkt);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
+ return ret;
+ }
+
+ ret = avcodec_receive_frame(s->avctx_mjpeg, s->jpgframe);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "JPEG decoding error: %s.\n", av_err2str(ret));
+
+ /* Normally skip, error if explode */
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ return AVERROR_INVALIDDATA;
+ else
+ return 0;
+ }
+
+ is_u16 = (s->bpp > 8);
+
+ /* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */
+
+ if (s->jpgframe->width != s->avctx_mjpeg->width ||
+ s->jpgframe->height != s->avctx_mjpeg->height ||
+ s->jpgframe->format != s->avctx_mjpeg->pix_fmt)
+ return AVERROR_INVALIDDATA;
+
+ /* See dng_blit for explanation */
+ if (s->avctx_mjpeg->width == w * 2 &&
+ s->avctx_mjpeg->height == h / 2 &&
+ s->avctx_mjpeg->pix_fmt == AV_PIX_FMT_GRAY16LE) {
+ is_single_comp = 1;
+ } else if (s->avctx_mjpeg->width >= w &&
+ s->avctx_mjpeg->height >= h &&
+ s->avctx_mjpeg->pix_fmt == (is_u16 ? AV_PIX_FMT_GRAY16 : AV_PIX_FMT_GRAY8)
+ ) {
+ is_single_comp = 0;
+ } else
+ return AVERROR_INVALIDDATA;
+
+ pixel_size = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t));
+
+ if (is_single_comp && !is_u16) {
+ av_log(s->avctx, AV_LOG_ERROR, "DNGs with bpp <= 8 and 1 component are unsupported\n");
+ av_frame_unref(s->jpgframe);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ dst_offset = dst_x + frame->linesize[0] * dst_y / pixel_size;
+ dst_data = frame->data[0] + dst_offset * pixel_size;
+ src_data = s->jpgframe->data[0];
+
+ dng_blit(s,
+ dst_data,
+ frame->linesize[0] / pixel_size,
+ src_data,
+ s->jpgframe->linesize[0] / pixel_size,
+ w,
+ h,
+ is_single_comp,
+ is_u16);
+
+ av_frame_unref(s->jpgframe);
+
+ return 0;
+}
+
+static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame)
+{
+ TiffContext *s = avctx->priv_data;
+
+ s->jpgframe->width = s->width;
+ s->jpgframe->height = s->height;
+
+ s->avctx_mjpeg->width = s->width;
+ s->avctx_mjpeg->height = s->height;
+
+ return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height);
+}
+