diff mbox series

[FFmpeg-devel,1/2] avcodec/tiff: Avoid forward declarations

Message ID HE1PR0301MB21544FCF0B06BFCC16F289118F7D9@HE1PR0301MB2154.eurprd03.prod.outlook.com
State Accepted
Headers show
Series [FFmpeg-devel,1/2] avcodec/tiff: Avoid forward declarations
Related show

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

Andreas Rheinhardt March 30, 2021, 7:56 a.m. UTC
In this case it also fixes a potential for compilation failures:
Not all compilers can handle the case in which a function with
a forward declaration declared with an attribute to always inline it
is called before the function body appears.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
This is of course designed as an alternative to Pavel's patch
https://ffmpeg.org/pipermail/ffmpeg-devel/2021-March/278383.html

 libavcodec/tiff.c | 392 +++++++++++++++++++++++-----------------------
 1 file changed, 193 insertions(+), 199 deletions(-)

Comments

Pavel Koshevoy March 30, 2021, 3:06 p.m. UTC | #1
On Tue, Mar 30, 2021 at 2:11 AM Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> wrote:

> In this case it also fixes a potential for compilation failures:
> Not all compilers can handle the case in which a function with
> a forward declaration declared with an attribute to always inline it
> is called before the function body appears.
>
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
> This is of course designed as an alternative to Pavel's patch
> https://ffmpeg.org/pipermail/ffmpeg-devel/2021-March/278383.html
>
>  libavcodec/tiff.c | 392 +++++++++++++++++++++++-----------------------
>  1 file changed, 193 insertions(+), 199 deletions(-)
>
> diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
> index 0878098b90..1d72fdc720 100644
> --- a/libavcodec/tiff.c
> +++ b/libavcodec/tiff.c
> @@ -275,9 +275,99 @@ static int add_metadata(int count, int type,
>      };
>  }
>
> +/**
> + * Map stored raw sensor values into linear reference values (see: DNG
> Specification - Chapter 5)
> + */
> +static uint16_t av_always_inline dng_process_color16(uint16_t value,
> +                                                     const uint16_t *lut,
> +                                                     uint16_t black_level,
> +                                                     float scale_factor) {
> +    float value_norm;
> +
> +    // Lookup table lookup
> +    if (lut)
> +        value = lut[value];
> +
> +    // Black level subtraction
> +    value = av_clip_uint16_c((unsigned)value - black_level);
> +
> +    // Color scaling
> +    value_norm = (float)value * scale_factor;
> +
> +    value = av_clip_uint16_c(value_norm * 65535);
> +
> +    return value;
> +}
> +
> +static uint16_t av_always_inline dng_process_color8(uint16_t value,
> +                                                    const uint16_t *lut,
> +                                                    uint16_t black_level,
> +                                                    float scale_factor) {
> +    return dng_process_color16(value, lut, black_level, scale_factor) >>
> 8;
> +}
> +
>  static void av_always_inline dng_blit(TiffContext *s, uint8_t *dst, int
> dst_stride,
>                                        const uint8_t *src, int src_stride,
> int width, int height,
> -                                      int is_single_comp, int is_u16);
> +                                      int is_single_comp, int is_u16)
> +{
> +    int line, col;
> +    float scale_factor;
> +
> +    scale_factor = 1.0f / (s->white_level - s->black_level);
> +
> +    if (is_single_comp) {
> +        if (!is_u16)
> +            return; /* <= 8bpp unsupported */
> +
> +        /* Image is double the width and half the height we need, each
> row comprises 2 rows of the output
> +           (split vertically in the middle). */
> +        for (line = 0; line < height / 2; line++) {
> +            uint16_t *dst_u16 = (uint16_t *)dst;
> +            uint16_t *src_u16 = (uint16_t *)src;
> +
> +            /* Blit first half of input row row to initial row of output
> */
> +            for (col = 0; col < width; col++)
> +                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut,
> s->black_level, scale_factor);
> +
> +            /* Advance the destination pointer by a row (source pointer
> remains in the same place) */
> +            dst += dst_stride * sizeof(uint16_t);
> +            dst_u16 = (uint16_t *)dst;
> +
> +            /* Blit second half of input row row to next row of output */
> +            for (col = 0; col < width; col++)
> +                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut,
> s->black_level, scale_factor);
> +
> +            dst += dst_stride * sizeof(uint16_t);
> +            src += src_stride * sizeof(uint16_t);
> +        }
> +    } else {
> +        /* Input and output image are the same size and the MJpeg decoder
> has done per-component
> +           deinterleaving, so blitting here is straightforward. */
> +        if (is_u16) {
> +            for (line = 0; line < height; line++) {
> +                uint16_t *dst_u16 = (uint16_t *)dst;
> +                uint16_t *src_u16 = (uint16_t *)src;
> +
> +                for (col = 0; col < width; col++)
> +                    *dst_u16++ = dng_process_color16(*src_u16++,
> s->dng_lut, s->black_level, scale_factor);
> +
> +                dst += dst_stride * sizeof(uint16_t);
> +                src += src_stride * sizeof(uint16_t);
> +            }
> +        } else {
> +            for (line = 0; line < height; line++) {
> +                uint8_t *dst_u8 = dst;
> +                const uint8_t *src_u8 = src;
> +
> +                for (col = 0; col < width; col++)
> +                    *dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut,
> s->black_level, scale_factor);
> +
> +                dst += dst_stride;
> +                src += src_stride;
> +            }
> +        }
> +    }
> +}
>
>  static void av_always_inline horizontal_fill(TiffContext *s,
>                                               unsigned int bpp, uint8_t*
> dst,
> @@ -553,7 +643,108 @@ static int tiff_unpack_fax(TiffContext *s, uint8_t
> *dst, int stride,
>      return ret;
>  }
>
> -static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame);
> +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);
> +}
>
>  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst,
> int stride,
>                               const uint8_t *src, int size, int
> strip_start, int lines)
> @@ -780,190 +971,6 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame
> *p, uint8_t *dst, int strid
>      return 0;
>  }
>
> -/**
> - * Map stored raw sensor values into linear reference values (see: DNG
> Specification - Chapter 5)
> - */
> -static uint16_t av_always_inline dng_process_color16(uint16_t value,
> -                                                     const uint16_t *lut,
> -                                                     uint16_t black_level,
> -                                                     float scale_factor) {
> -    float value_norm;
> -
> -    // Lookup table lookup
> -    if (lut)
> -        value = lut[value];
> -
> -    // Black level subtraction
> -    value = av_clip_uint16_c((unsigned)value - black_level);
> -
> -    // Color scaling
> -    value_norm = (float)value * scale_factor;
> -
> -    value = av_clip_uint16_c(value_norm * 65535);
> -
> -    return value;
> -}
> -
> -static uint16_t av_always_inline dng_process_color8(uint16_t value,
> -                                                    const uint16_t *lut,
> -                                                    uint16_t black_level,
> -                                                    float scale_factor) {
> -    return dng_process_color16(value, lut, black_level, scale_factor) >>
> 8;
> -}
> -
> -static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
> -                     const uint8_t *src, int src_stride,
> -                     int width, int height, int is_single_comp, int
> is_u16)
> -{
> -    int line, col;
> -    float scale_factor;
> -
> -    scale_factor = 1.0f / (s->white_level - s->black_level);
> -
> -    if (is_single_comp) {
> -        if (!is_u16)
> -            return; /* <= 8bpp unsupported */
> -
> -        /* Image is double the width and half the height we need, each
> row comprises 2 rows of the output
> -           (split vertically in the middle). */
> -        for (line = 0; line < height / 2; line++) {
> -            uint16_t *dst_u16 = (uint16_t *)dst;
> -            uint16_t *src_u16 = (uint16_t *)src;
> -
> -            /* Blit first half of input row row to initial row of output
> */
> -            for (col = 0; col < width; col++)
> -                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut,
> s->black_level, scale_factor);
> -
> -            /* Advance the destination pointer by a row (source pointer
> remains in the same place) */
> -            dst += dst_stride * sizeof(uint16_t);
> -            dst_u16 = (uint16_t *)dst;
> -
> -            /* Blit second half of input row row to next row of output */
> -            for (col = 0; col < width; col++)
> -                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut,
> s->black_level, scale_factor);
> -
> -            dst += dst_stride * sizeof(uint16_t);
> -            src += src_stride * sizeof(uint16_t);
> -        }
> -    } else {
> -        /* Input and output image are the same size and the MJpeg decoder
> has done per-component
> -           deinterleaving, so blitting here is straightforward. */
> -        if (is_u16) {
> -            for (line = 0; line < height; line++) {
> -                uint16_t *dst_u16 = (uint16_t *)dst;
> -                uint16_t *src_u16 = (uint16_t *)src;
> -
> -                for (col = 0; col < width; col++)
> -                    *dst_u16++ = dng_process_color16(*src_u16++,
> s->dng_lut, s->black_level, scale_factor);
> -
> -                dst += dst_stride * sizeof(uint16_t);
> -                src += src_stride * sizeof(uint16_t);
> -            }
> -        } else {
> -            for (line = 0; line < height; line++) {
> -                uint8_t *dst_u8 = dst;
> -                const uint8_t *src_u8 = src;
> -
> -                for (col = 0; col < width; col++)
> -                    *dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut,
> s->black_level, scale_factor);
> -
> -                dst += dst_stride;
> -                src += src_stride;
> -            }
> -        }
> -    }
> -}
> -
> -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_tiles(AVCodecContext *avctx, AVFrame *frame,
>                              const AVPacket *avpkt)
>  {
> @@ -1040,19 +1047,6 @@ static int dng_decode_tiles(AVCodecContext *avctx,
> AVFrame *frame,
>      return avpkt->size;
>  }
>
> -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);
> -}
> -
>  static int init_image(TiffContext *s, ThreadFrame *frame)
>  {
>      int ret;
> --
> 2.27.0
>


LGTM ... I wasn't sure about declaring a function more than a couple lines
long as inline.
diff mbox series

Patch

diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 0878098b90..1d72fdc720 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -275,9 +275,99 @@  static int add_metadata(int count, int type,
     };
 }
 
+/**
+ * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5)
+ */
+static uint16_t av_always_inline dng_process_color16(uint16_t value,
+                                                     const uint16_t *lut,
+                                                     uint16_t black_level,
+                                                     float scale_factor) {
+    float value_norm;
+
+    // Lookup table lookup
+    if (lut)
+        value = lut[value];
+
+    // Black level subtraction
+    value = av_clip_uint16_c((unsigned)value - black_level);
+
+    // Color scaling
+    value_norm = (float)value * scale_factor;
+
+    value = av_clip_uint16_c(value_norm * 65535);
+
+    return value;
+}
+
+static uint16_t av_always_inline dng_process_color8(uint16_t value,
+                                                    const uint16_t *lut,
+                                                    uint16_t black_level,
+                                                    float scale_factor) {
+    return dng_process_color16(value, lut, black_level, scale_factor) >> 8;
+}
+
 static void av_always_inline dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
                                       const uint8_t *src, int src_stride, int width, int height,
-                                      int is_single_comp, int is_u16);
+                                      int is_single_comp, int is_u16)
+{
+    int line, col;
+    float scale_factor;
+
+    scale_factor = 1.0f / (s->white_level - s->black_level);
+
+    if (is_single_comp) {
+        if (!is_u16)
+            return; /* <= 8bpp unsupported */
+
+        /* Image is double the width and half the height we need, each row comprises 2 rows of the output
+           (split vertically in the middle). */
+        for (line = 0; line < height / 2; line++) {
+            uint16_t *dst_u16 = (uint16_t *)dst;
+            uint16_t *src_u16 = (uint16_t *)src;
+
+            /* Blit first half of input row row to initial row of output */
+            for (col = 0; col < width; col++)
+                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
+
+            /* Advance the destination pointer by a row (source pointer remains in the same place) */
+            dst += dst_stride * sizeof(uint16_t);
+            dst_u16 = (uint16_t *)dst;
+
+            /* Blit second half of input row row to next row of output */
+            for (col = 0; col < width; col++)
+                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
+
+            dst += dst_stride * sizeof(uint16_t);
+            src += src_stride * sizeof(uint16_t);
+        }
+    } else {
+        /* Input and output image are the same size and the MJpeg decoder has done per-component
+           deinterleaving, so blitting here is straightforward. */
+        if (is_u16) {
+            for (line = 0; line < height; line++) {
+                uint16_t *dst_u16 = (uint16_t *)dst;
+                uint16_t *src_u16 = (uint16_t *)src;
+
+                for (col = 0; col < width; col++)
+                    *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
+
+                dst += dst_stride * sizeof(uint16_t);
+                src += src_stride * sizeof(uint16_t);
+            }
+        } else {
+            for (line = 0; line < height; line++) {
+                uint8_t *dst_u8 = dst;
+                const uint8_t *src_u8 = src;
+
+                for (col = 0; col < width; col++)
+                    *dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut, s->black_level, scale_factor);
+
+                dst += dst_stride;
+                src += src_stride;
+            }
+        }
+    }
+}
 
 static void av_always_inline horizontal_fill(TiffContext *s,
                                              unsigned int bpp, uint8_t* dst,
@@ -553,7 +643,108 @@  static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride,
     return ret;
 }
 
-static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame);
+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);
+}
 
 static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride,
                              const uint8_t *src, int size, int strip_start, int lines)
@@ -780,190 +971,6 @@  static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
     return 0;
 }
 
-/**
- * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5)
- */
-static uint16_t av_always_inline dng_process_color16(uint16_t value,
-                                                     const uint16_t *lut,
-                                                     uint16_t black_level,
-                                                     float scale_factor) {
-    float value_norm;
-
-    // Lookup table lookup
-    if (lut)
-        value = lut[value];
-
-    // Black level subtraction
-    value = av_clip_uint16_c((unsigned)value - black_level);
-
-    // Color scaling
-    value_norm = (float)value * scale_factor;
-
-    value = av_clip_uint16_c(value_norm * 65535);
-
-    return value;
-}
-
-static uint16_t av_always_inline dng_process_color8(uint16_t value,
-                                                    const uint16_t *lut,
-                                                    uint16_t black_level,
-                                                    float scale_factor) {
-    return dng_process_color16(value, lut, black_level, scale_factor) >> 8;
-}
-
-static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
-                     const uint8_t *src, int src_stride,
-                     int width, int height, int is_single_comp, int is_u16)
-{
-    int line, col;
-    float scale_factor;
-
-    scale_factor = 1.0f / (s->white_level - s->black_level);
-
-    if (is_single_comp) {
-        if (!is_u16)
-            return; /* <= 8bpp unsupported */
-
-        /* Image is double the width and half the height we need, each row comprises 2 rows of the output
-           (split vertically in the middle). */
-        for (line = 0; line < height / 2; line++) {
-            uint16_t *dst_u16 = (uint16_t *)dst;
-            uint16_t *src_u16 = (uint16_t *)src;
-
-            /* Blit first half of input row row to initial row of output */
-            for (col = 0; col < width; col++)
-                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
-
-            /* Advance the destination pointer by a row (source pointer remains in the same place) */
-            dst += dst_stride * sizeof(uint16_t);
-            dst_u16 = (uint16_t *)dst;
-
-            /* Blit second half of input row row to next row of output */
-            for (col = 0; col < width; col++)
-                *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
-
-            dst += dst_stride * sizeof(uint16_t);
-            src += src_stride * sizeof(uint16_t);
-        }
-    } else {
-        /* Input and output image are the same size and the MJpeg decoder has done per-component
-           deinterleaving, so blitting here is straightforward. */
-        if (is_u16) {
-            for (line = 0; line < height; line++) {
-                uint16_t *dst_u16 = (uint16_t *)dst;
-                uint16_t *src_u16 = (uint16_t *)src;
-
-                for (col = 0; col < width; col++)
-                    *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
-
-                dst += dst_stride * sizeof(uint16_t);
-                src += src_stride * sizeof(uint16_t);
-            }
-        } else {
-            for (line = 0; line < height; line++) {
-                uint8_t *dst_u8 = dst;
-                const uint8_t *src_u8 = src;
-
-                for (col = 0; col < width; col++)
-                    *dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut, s->black_level, scale_factor);
-
-                dst += dst_stride;
-                src += src_stride;
-            }
-        }
-    }
-}
-
-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_tiles(AVCodecContext *avctx, AVFrame *frame,
                             const AVPacket *avpkt)
 {
@@ -1040,19 +1047,6 @@  static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame,
     return avpkt->size;
 }
 
-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);
-}
-
 static int init_image(TiffContext *s, ThreadFrame *frame)
 {
     int ret;