Message ID | 20190809162959.17924-10-velocityra@gmail.com |
---|---|
State | Superseded |
Headers | show |
On Fri, Aug 09, 2019 at 07:29:55PM +0300, Nick Renieris wrote: > From: Nick Renieris <velocityra@gmail.com> > > This enables decoding of DNG images generated by the 'DJI Zenmuse X7' > digital camera > Samples: https://www.dji.com/gr/zenmuse-x7/info#downloads > > Signed-off-by: Nick Renieris <velocityra@gmail.com> > --- > libavcodec/tiff.c | 61 +++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 51 insertions(+), 10 deletions(-) after this commit the code dies when used with ffplay with floating point exceptions ./ffplay pentax_k1_69.dng ... [tiff @ 0x7f8a68002540] Assuming black level pattern values are identical Floating point exception (core dumped) vq= 0KB sq= 0B f=0/0 [...]
> after this commit the code dies when used with ffplay with floating point > exceptions I tried this on Ubuntu and I can't repro, it works fine. Maybe something I changed locally fixed it, please re-test on the new revision I'll send in a bit.
On Sun, Aug 11, 2019 at 12:57:17AM +0300, Nick Renieris wrote: > > after this commit the code dies when used with ffplay with floating point > > exceptions > > I tried this on Ubuntu and I can't repro, it works fine. > Maybe something I changed locally fixed it, please re-test on the new > revision I'll send in a bit. yes, it behaved a bit odd, ill retest with the new patches tomorrow (need to sleep) some things i noticed in the previous ones though it disappeared with some commits in the previous set too it doesnt happen with ffmpeg and i have this half useless backtrace: #0 0x00000000004752cc in dng_decode.isra () #1 0x0000000000b73b67 in decode_frame () #2 0x00000000008668d7 in decode_receive_frame_internal () #3 0x0000000000867488 in avcodec_send_packet () #4 0x00000000007c002d in try_decode_frame () #5 0x00000000007c8ad8 in avformat_find_stream_info () #6 0x00000000004c2b09 in read_thread () ill provide better information tomorrow in case it still happens with the latest set Thanks [...]
On Sun, Aug 11, 2019 at 01:29:44AM +0200, Michael Niedermayer wrote: > On Sun, Aug 11, 2019 at 12:57:17AM +0300, Nick Renieris wrote: > > > after this commit the code dies when used with ffplay with floating point > > > exceptions > > > > I tried this on Ubuntu and I can't repro, it works fine. > > Maybe something I changed locally fixed it, please re-test on the new > > revision I'll send in a bit. > > yes, it behaved a bit odd, ill retest with the new patches tomorrow (need to sleep) > some things i noticed in the previous ones though > it disappeared with some commits in the previous set too > it doesnt happen with ffmpeg > and i have this half useless backtrace: > #0 0x00000000004752cc in dng_decode.isra () > #1 0x0000000000b73b67 in decode_frame () > #2 0x00000000008668d7 in decode_receive_frame_internal () > #3 0x0000000000867488 in avcodec_send_packet () > #4 0x00000000007c002d in try_decode_frame () > #5 0x00000000007c8ad8 in avformat_find_stream_info () > #6 0x00000000004c2b09 in read_thread () > > ill provide better information tomorrow in case it still happens > with the latest set also occurs with the latest patchset (minus the last 3 patches) heres a proper backtrace: Program received signal SIGFPE, Arithmetic exception. [Switching to Thread 0x7fffdb6a5700 (LWP 19427)] 0x0000000000c4bad1 in dng_decode_tiles (avctx=0x7fffcc002540, frame=0x7fffcc003200) at libavcodec/tiff.c:947 947 has_width_leftover = (s->width % s->tile_width != 0); (gdb) bt Python Exception <type 'exceptions.ImportError'> No module named gdb.frames: #0 0x0000000000c4bad1 in dng_decode_tiles (avctx=0x7fffcc002540, frame=0x7fffcc003200) at libavcodec/tiff.c:947 #1 0x0000000000c4bd95 in dng_decode (avctx=0x7fffcc002540, frame=0x7fffcc003200, avpkt=0x7fffcc003540) at libavcodec/tiff.c:1011 #2 0x0000000000c4fcc4 in decode_frame (avctx=0x7fffcc002540, data=0x7fffcc003200, got_frame=0x7fffdb6a46e8, avpkt=0x7fffcc003540) at libavcodec/tiff.c:1893 #3 0x00000000009005fa in decode_simple_internal (avctx=0x7fffcc002540, frame=0x7fffcc003200) at libavcodec/decode.c:433 #4 0x0000000000901281 in decode_simple_receive_frame (avctx=0x7fffcc002540, frame=0x7fffcc003200) at libavcodec/decode.c:629 #5 0x000000000090134c in decode_receive_frame_internal (avctx=0x7fffcc002540, frame=0x7fffcc003200) at libavcodec/decode.c:647 #6 0x00000000009015a7 in avcodec_send_packet (avctx=0x7fffcc002540, avpkt=0x7fffdb6a4890) at libavcodec/decode.c:705 #7 0x000000000083415b in try_decode_frame (s=0x7fffcc000940, st=0x7fffcc001c80, avpkt=0x7fffdb6a4a40, options=0x7fffcc001380) at libavformat/utils.c:3080 #8 0x000000000083752c in avformat_find_stream_info (ic=0x7fffcc000940, options=0x7fffcc001380) at libavformat/utils.c:3903 #9 0x0000000000422573 in read_thread (arg=0x7fffdb6a6040) at fftools/ffplay.c:2805 #10 0x00007ffff5f1f2ed in SDL_RunThread (data=0x2996dd0) at SDL2-2.0.4/src/thread/SDL_thread.c:282 #11 0x00007ffff5f7d1a9 in RunThread (data=<optimized out>) at SDL2-2.0.4/src/thread/pthread/SDL_systhread.c:75 #12 0x00007ffff0249184 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0 #13 0x00007fffeff7603d in clone () from /lib/x86_64-linux-gnu/libc.so.6 [...]
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index cf8965453c..ecd87c0b2f 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -274,7 +274,8 @@ static int add_metadata(int count, int type, } 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_u16); + const uint8_t *src, int src_stride, int width, int height, + int is_single_comp, int is_u16); static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, @@ -698,6 +699,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid 0, // no stride, only 1 line width / pixel_size_bytes * pixel_size_bits / s->bpp, // need to account for [1, 16] bpp 1, + 0, // single-component variation is only preset in JPEG-encoded DNGs is_u16); } @@ -795,18 +797,32 @@ static uint16_t av_always_inline dng_process_color8(uint16_t value, 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_u16) + 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_u16) { - for (line = 0; line < height; line++) { + 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); @@ -814,12 +830,27 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, src += src_stride * sizeof(uint16_t); } } else { - for (line = 0; line < height; line++) { - for (col = 0; col < width; col++) - *dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); + /* 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++) { + for (col = 0; col < width; col++) + *dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); - dst += dst_stride; - src += src_stride; + dst += dst_stride; + src += src_stride; + } } } } @@ -831,7 +862,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, AVPacket jpkt; uint8_t *dst_data, *src_data; uint32_t dst_offset; /* offset from dst buffer in pixels */ - int is_u16, pixel_size; + int is_single_comp, is_u16, pixel_size; int ret; /* Prepare a packet and send to the MJPEG decoder */ @@ -865,9 +896,18 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, /* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */ + /* See dng_blit for explanation */ + is_single_comp = (s->avctx_mjpeg->width == w * 2 && s->avctx_mjpeg->height == h / 2); + is_u16 = (s->bpp > 8); 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 = x + frame->linesize[0] * y / pixel_size; dst_data = frame->data[0] + dst_offset * pixel_size; src_data = s->jpgframe->data[0]; @@ -879,6 +919,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, s->jpgframe->linesize[0] / pixel_size, w, h, + is_single_comp, is_u16); av_frame_unref(s->jpgframe);