mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-02-04 06:08:26 +02:00
avcodec/tiff: Avoid forward declarations
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. E.g. GCC 4.2.1 on OS X 10.6 doesn't like it. Reviewed-by: Pavel Koshevoy <pkoshevoy@gmail.com> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com> (cherry picked from commit e5d6af7b35d97f5c1252ecf8bd61f3295909fb6c)
This commit is contained in:
parent
1761cc0cb0
commit
5621d10b7a
@ -275,9 +275,101 @@ 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 +645,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 +973,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 +1049,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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user