Re: [FFmpeg-devel] [PATCH 2/2] avcodec/tiff: Multi-page support
Any news on this? Is there something I should do? Στις Σάβ, 23 Μαρ 2019 στις 2:54 μ.μ., ο/η Carl Eugen Hoyos έγραψε: > > 2019-03-23 13:34 GMT+01:00, Paul B Mahol : > > On 3/23/19, Carl Eugen Hoyos wrote: > >> 2019-03-23 9:11 GMT+01:00, Paul B Mahol : > >>> On 3/22/19, Carl Eugen Hoyos wrote: > >>>> 2019-03-22 15:50 GMT+01:00, velocit...@gmail.com : > >>>>> From: Nick Renieris > >>>>> > >>>>> Option "-page N" (page index N starts from 1) can now > >>>>> be used to specify which TIFF page/subfile to decode. > >>>> > >>>> What is the current behaviour? > >>>> Shouldn't the decoder output all pages as for a video file? > >>> > >>> How? > >> > >> I would have suggested decoder flush. > > The word is probably "drain". > > > What? Can you elaborate what you think? > > Isn't there a return value that leads to subsequent calls of > AVCodec->decode()? > > Carl Eugen > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 2/2] avcodec/tiff: Multi-page support
I haven't, is there a specific place that it's preferred I upload it to? Στις Πέμ, 28 Μαρ 2019 στις 1:12 μ.μ., ο/η Paul B Mahol έγραψε: > > On 3/28/19, Nick Renieris wrote: > > Any news on this? Is there something I should do? > > Have you uploaded small tiff so this patch can be tested? > > > > > Στις Σάβ, 23 Μαρ 2019 στις 2:54 μ.μ., ο/η Carl Eugen Hoyos > > έγραψε: > >> > >> 2019-03-23 13:34 GMT+01:00, Paul B Mahol : > >> > On 3/23/19, Carl Eugen Hoyos wrote: > >> >> 2019-03-23 9:11 GMT+01:00, Paul B Mahol : > >> >>> On 3/22/19, Carl Eugen Hoyos wrote: > >> >>>> 2019-03-22 15:50 GMT+01:00, velocit...@gmail.com > >> >>>> : > >> >>>>> From: Nick Renieris > >> >>>>> > >> >>>>> Option "-page N" (page index N starts from 1) can now > >> >>>>> be used to specify which TIFF page/subfile to decode. > >> >>>> > >> >>>> What is the current behaviour? > >> >>>> Shouldn't the decoder output all pages as for a video file? > >> >>> > >> >>> How? > >> >> > >> >> I would have suggested decoder flush. > >> > >> The word is probably "drain". > >> > >> > What? Can you elaborate what you think? > >> > >> Isn't there a return value that leads to subsequent calls of > >> AVCodec->decode()? > >> > >> Carl Eugen > >> ___ > >> ffmpeg-devel mailing list > >> ffmpeg-devel@ffmpeg.org > >> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> > >> To unsubscribe, visit link above, or email > >> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > > ___ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > To unsubscribe, visit link above, or email > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 2/2] avcodec/tiff: Multi-page support
When I made the patch I did ask you on IRC whether I should upload something and got no answer. Στις Πέμ, 28 Μαρ 2019 στις 2:58 μ.μ., ο/η Nick Renieris έγραψε: > > I haven't, is there a specific place that it's preferred I upload it to? > > Στις Πέμ, 28 Μαρ 2019 στις 1:12 μ.μ., ο/η Paul B Mahol > έγραψε: > > > > On 3/28/19, Nick Renieris wrote: > > > Any news on this? Is there something I should do? > > > > Have you uploaded small tiff so this patch can be tested? > > > > > > > > Στις Σάβ, 23 Μαρ 2019 στις 2:54 μ.μ., ο/η Carl Eugen Hoyos > > > έγραψε: > > >> > > >> 2019-03-23 13:34 GMT+01:00, Paul B Mahol : > > >> > On 3/23/19, Carl Eugen Hoyos wrote: > > >> >> 2019-03-23 9:11 GMT+01:00, Paul B Mahol : > > >> >>> On 3/22/19, Carl Eugen Hoyos wrote: > > >> >>>> 2019-03-22 15:50 GMT+01:00, velocit...@gmail.com > > >> >>>> : > > >> >>>>> From: Nick Renieris > > >> >>>>> > > >> >>>>> Option "-page N" (page index N starts from 1) can now > > >> >>>>> be used to specify which TIFF page/subfile to decode. > > >> >>>> > > >> >>>> What is the current behaviour? > > >> >>>> Shouldn't the decoder output all pages as for a video file? > > >> >>> > > >> >>> How? > > >> >> > > >> >> I would have suggested decoder flush. > > >> > > >> The word is probably "drain". > > >> > > >> > What? Can you elaborate what you think? > > >> > > >> Isn't there a return value that leads to subsequent calls of > > >> AVCodec->decode()? > > >> > > >> Carl Eugen > > >> ___ > > >> ffmpeg-devel mailing list > > >> ffmpeg-devel@ffmpeg.org > > >> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > >> > > >> To unsubscribe, visit link above, or email > > >> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > > > ___ > > > ffmpeg-devel mailing list > > > ffmpeg-devel@ffmpeg.org > > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > > > To unsubscribe, visit link above, or email > > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > > ___ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > To unsubscribe, visit link above, or email > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 2/2] avcodec/tiff: Multi-page support
Ok, here's a multipage tif with 3 pages, the two first are blue and the last one red: https://0x0.st/zKdB.tif Στις Πέμ, 28 Μαρ 2019 στις 4:35 μ.μ., ο/η Paul B Mahol έγραψε: > > On 3/28/19, Nick Renieris wrote: > > When I made the patch I did ask you on IRC whether I should upload > > something and got no answer. > > > > Please upload it, somewhere like https://0x0.st/ > > > Στις Πέμ, 28 Μαρ 2019 στις 2:58 μ.μ., ο/η Nick Renieris > > έγραψε: > >> > >> I haven't, is there a specific place that it's preferred I upload it to? > >> > >> Στις Πέμ, 28 Μαρ 2019 στις 1:12 μ.μ., ο/η Paul B Mahol > >> έγραψε: > >> > > >> > On 3/28/19, Nick Renieris wrote: > >> > > Any news on this? Is there something I should do? > >> > > >> > Have you uploaded small tiff so this patch can be tested? > >> > > >> > > > >> > > Στις Σάβ, 23 Μαρ 2019 στις 2:54 μ.μ., ο/η Carl Eugen Hoyos > >> > > έγραψε: > >> > >> > >> > >> 2019-03-23 13:34 GMT+01:00, Paul B Mahol : > >> > >> > On 3/23/19, Carl Eugen Hoyos wrote: > >> > >> >> 2019-03-23 9:11 GMT+01:00, Paul B Mahol : > >> > >> >>> On 3/22/19, Carl Eugen Hoyos wrote: > >> > >> >>>> 2019-03-22 15:50 GMT+01:00, velocit...@gmail.com > >> > >> >>>> : > >> > >> >>>>> From: Nick Renieris > >> > >> >>>>> > >> > >> >>>>> Option "-page N" (page index N starts from 1) can now > >> > >> >>>>> be used to specify which TIFF page/subfile to decode. > >> > >> >>>> > >> > >> >>>> What is the current behaviour? > >> > >> >>>> Shouldn't the decoder output all pages as for a video file? > >> > >> >>> > >> > >> >>> How? > >> > >> >> > >> > >> >> I would have suggested decoder flush. > >> > >> > >> > >> The word is probably "drain". > >> > >> > >> > >> > What? Can you elaborate what you think? > >> > >> > >> > >> Isn't there a return value that leads to subsequent calls of > >> > >> AVCodec->decode()? > >> > >> > >> > >> Carl Eugen > >> > >> ___ > >> > >> ffmpeg-devel mailing list > >> > >> ffmpeg-devel@ffmpeg.org > >> > >> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> > >> > >> > >> To unsubscribe, visit link above, or email > >> > >> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > >> > > ___ > >> > > ffmpeg-devel mailing list > >> > > ffmpeg-devel@ffmpeg.org > >> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> > > > >> > > To unsubscribe, visit link above, or email > >> > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > >> > ___ > >> > ffmpeg-devel mailing list > >> > ffmpeg-devel@ffmpeg.org > >> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> > > >> > To unsubscribe, visit link above, or email > >> > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > > ___ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > To unsubscribe, visit link above, or email > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 2/2] avcodec/tiff: Multi-page support
Huh? No I fixed that, it's AV_OPT_TYPE_INT now. See the second email in this list (first was the initial patch, then the corrected patch). Στις Παρ, 29 Μαρ 2019 στις 12:51 π.μ., ο/η Paul B Mahol έγραψε: > > On 3/28/19, Nick Renieris wrote: > > Ok, here's a multipage tif with 3 pages, the two first are blue and > > the last one red: > > https://0x0.st/zKdB.tif > > > > Patch contains UINT16 opt and as is can not be applied. > Please fix that. > > > Στις Πέμ, 28 Μαρ 2019 στις 4:35 μ.μ., ο/η Paul B Mahol > > έγραψε: > >> > >> On 3/28/19, Nick Renieris wrote: > >> > When I made the patch I did ask you on IRC whether I should upload > >> > something and got no answer. > >> > > >> > >> Please upload it, somewhere like https://0x0.st/ > >> > >> > Στις Πέμ, 28 Μαρ 2019 στις 2:58 μ.μ., ο/η Nick Renieris > >> > έγραψε: > >> >> > >> >> I haven't, is there a specific place that it's preferred I upload it > >> >> to? > >> >> > >> >> Στις Πέμ, 28 Μαρ 2019 στις 1:12 μ.μ., ο/η Paul B Mahol > >> >> έγραψε: > >> >> > > >> >> > On 3/28/19, Nick Renieris wrote: > >> >> > > Any news on this? Is there something I should do? > >> >> > > >> >> > Have you uploaded small tiff so this patch can be tested? > >> >> > > >> >> > > > >> >> > > Στις Σάβ, 23 Μαρ 2019 στις 2:54 μ.μ., ο/η Carl Eugen Hoyos > >> >> > > έγραψε: > >> >> > >> > >> >> > >> 2019-03-23 13:34 GMT+01:00, Paul B Mahol : > >> >> > >> > On 3/23/19, Carl Eugen Hoyos wrote: > >> >> > >> >> 2019-03-23 9:11 GMT+01:00, Paul B Mahol : > >> >> > >> >>> On 3/22/19, Carl Eugen Hoyos wrote: > >> >> > >> >>>> 2019-03-22 15:50 GMT+01:00, velocit...@gmail.com > >> >> > >> >>>> : > >> >> > >> >>>>> From: Nick Renieris > >> >> > >> >>>>> > >> >> > >> >>>>> Option "-page N" (page index N starts from 1) can now > >> >> > >> >>>>> be used to specify which TIFF page/subfile to decode. > >> >> > >> >>>> > >> >> > >> >>>> What is the current behaviour? > >> >> > >> >>>> Shouldn't the decoder output all pages as for a video file? > >> >> > >> >>> > >> >> > >> >>> How? > >> >> > >> >> > >> >> > >> >> I would have suggested decoder flush. > >> >> > >> > >> >> > >> The word is probably "drain". > >> >> > >> > >> >> > >> > What? Can you elaborate what you think? > >> >> > >> > >> >> > >> Isn't there a return value that leads to subsequent calls of > >> >> > >> AVCodec->decode()? > >> >> > >> > >> >> > >> Carl Eugen > >> >> > >> ___ > >> >> > >> ffmpeg-devel mailing list > >> >> > >> ffmpeg-devel@ffmpeg.org > >> >> > >> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> >> > >> > >> >> > >> To unsubscribe, visit link above, or email > >> >> > >> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > >> >> > > ___ > >> >> > > ffmpeg-devel mailing list > >> >> > > ffmpeg-devel@ffmpeg.org > >> >> > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> >> > > > >> >> > > To unsubscribe, visit link above, or email > >> >> > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > >> >> > ___ > >> >> > ffmpeg-devel mailing list > >> >> > ffmpeg-devel@ffmpeg.org > >> >> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> >> > > >> >> > To unsubscribe, visit link above, or email > >> >> > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > >> > ___ > >> > ffmpeg-devel mailing list > >> > ffmpeg-devel@ffmpeg.org > >> > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> > > >> > To unsubscribe, visit link above, or email > >> > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > >> ___ > >> ffmpeg-devel mailing list > >> ffmpeg-devel@ffmpeg.org > >> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > >> > >> To unsubscribe, visit link above, or email > >> ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > > ___ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > To unsubscribe, visit link above, or email > > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 2/2] avcodec/tiff: Multi-page support
Στις Παρ, 29 Μαρ 2019 στις 11:05 π.μ., ο/η Paul B Mahol έγραψε: > You should also check max number of available pages. > And issue warning if user requested more than available and than provide some > page. Yeah, I _would_ have done that, but the images I've seen don't actually contain the max number of pages in PageNumber[1]. Instead, they seem to contain PageNumber[0] + 1. Here's an example from the file I sent (generated with IrfanView): https://i.imgur.com/CEWADrD.png The PageNumber tag from the last IFD couldn't fit in the screenshot, it's PageNumber[0] = 2 and PageNumber[1] = 3. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avcodec/tiff: Add support for recognizing DNG files
Any consensus on using libdng? Στις Τετ, 20 Μαρ 2019 στις 5:03 μ.μ., ο/η Nick Renieris έγραψε: > > Στις Τετ, 20 Μαρ 2019 στις 4:17 μ.μ., ο/η Paul B Mahol > έγραψε: > > DNG I posted should be decodeable by default, without need for extra > > option(s). > > The DNG contents themselves? As in, not just the thumbnail? That's > what the whole GSoC proposal is about though... What about: > >On Tue, Mar 19, 2019 at 03:03:20AM +0200, Nick Renieris wrote: > >Not to mention, this patch is for preliminary support, I don't suppose you > >require a massive patchset that implements everything altogether? Besides, > >GSoC requirements state that I need to get a minor patch in, before I can > >even apply. This is what this patch is for. > > > The subimage option is intended to decode Nth image as is stored in file. > > Nth image? The option is a boolean. > > _If_ it was an integer though: > > Given what you said, for -thumbnail I would need to check for > NewSubfileType's Bit0==1 and for -subimage, Bit1==1? > (Here's where I'm getting my info from so that we're on the same page: > https://www.awaresystems.be/imaging/tiff/tifftags/newsubfiletype.html) > > But it's not an integer as far as I can see, so all of the above is > out of scope for this patch. > > > The thumbnail option should be implemented to decode only first/best > > thumbnail. > > Sounds easy enough. > > > There is way to detect them and ignore them when not that option is set. > > Detect/ignore the thumbnails? Yes, that's easy. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avcodec/tiff: Add support for recognizing DNG files
I don't mind either way, but I'm writing my GSoC proposal at the moment and wanted an answer. If there's no clear answer, is it something TBD that I don't need to specify in the proposal? ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avcodec/tiff: Add support for recognizing DNG/CinemaDNG files
This was meant to be a reply to http://ffmpeg.org/pipermail/ffmpeg-devel/2019-May/244744.html ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avcodec/tiff: Add support for recognizing DNG/CinemaDNG files
Do not review, I found some CinemaDNG images that do not work. I will figure out a better solution. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Please don't review this yet. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v2 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Some sample working DNGs: https://0x0.st/z8pf.dng (non-jpeg) https://www.kenrockwell.com/leica/m9/sample-photos-3.htm (jpeg. these are decoded as dark because there's no color space conversion implemented) A few others work too but I can't find the links to them anymore, I can upload them if requested. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v3 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Ready for review. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v3 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
I have a small patch for basic gamma correction, it makes the dark images look much better. Should I send it here (if so, just as a single email reply to this?) or wait until this patchset is merged? ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v3 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Some example DNGs before/after the gamma correction: https://i.imgur.com/m3Qgrwb.jpg https://i.imgur.com/XgggT2h.jpg These are not full size of course, just screenshots. Colors are wrong and I'm pretty sure I know why, that's TODO. Στις Τετ, 24 Ιουλ 2019 στις 12:04 μ.μ., ο/η Nick Renieris έγραψε: > > I have a small patch for basic gamma correction, it makes the dark > images look much better. > Should I send it here (if so, just as a single email reply to this?) > or wait until this patchset is merged? ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] lavc/tiff: Decode embedded JPEGs in DNG images
The latest patch is unrelated to the gamma stuff (which in hindsight isn't accurately implemented, so never mind), it has a regression fix for z8pf.dng and adds compatibility to the following: https://www.camerafv5.com/pages/raw-samples.php https://www.camerafv5.com/pages/nexus6-raw-samples.php https://www.chris-juettner.de/projekte/raw-samples-comparison-download/dji-mavic-air etc >Do you plan to implement camera native RGB to CIE XYZ mapping as specified in DNG Spec 1.4.0.0 Chapter 6 ? Perhaps. I haven't looked at it much but it may be too much work for the time I have left, I will talk with my mentor on whether to prioritize it (a lot of images look fine without it). Στις Τετ, 24 Ιουλ 2019 στις 1:06 μ.μ., ο/η έγραψε: > > From: Nick Renieris > > Used a technique similar to lavc/tdsc.c for invoking the MJPEG decoder. > > This commit adds support for: > - DNG tiles > - DNG tile huffman lossless JPEG decoding > - DNG color scaling [1] > - LinearizationTable tag > - BlackLevel tag > > [1]: As specified in the DNG Specification - Chapter 5 > > Signed-off-by: Nick Renieris > --- > libavcodec/tiff.c | 16 > 1 file changed, 16 deletions(-) > > diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c > index 423eaf0647..4f6ba256c6 100644 > --- a/libavcodec/tiff.c > +++ b/libavcodec/tiff.c > @@ -280,19 +280,6 @@ static void av_always_inline horizontal_fill(TiffContext > *s, > int usePtr, const uint8_t *src, > uint8_t c, int width, int > offset) > { > -/* Handle DNG images with uncompressed strips (non-tiled) */ > -if (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == > TIFF_TYPE_CINEMADNG) { > -dng_blit(s, > - dst + offset, > - width, > - src, > - width, > - width, > - 1, > - 0); > -return; > -} > - > switch (bpp) { > case 1: > while (--width >= 0) { > @@ -1799,9 +1786,6 @@ again: > } else if (s->is_tiled) { > av_log(avctx, AV_LOG_ERROR, "DNG uncompressed tiled images are > not supported\n"); > return AVERROR_PATCHWELCOME; > -} else if (s->bpp != 8) { > -av_log(avctx, AV_LOG_ERROR, "DNG uncompressed non-tiled non-8bpp > images are not supported\n"); > -return AVERROR_PATCHWELCOME; > } > } > > -- > 2.21.0.windows.1 > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v6 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Thanks for the review Moritz, pushed fixes. "outputted" is a word actually :) https://forum.wordreference.com/threads/is-outputted-a-word.2707379 Στις Πέμ, 25 Ιουλ 2019 στις 4:57 μ.μ., ο/η Moritz Barsnick έγραψε: > > On Thu, Jul 25, 2019 at 15:12:53 +0300, velocit...@gmail.com wrote: > > Nit: > > > tiff_decoder_suggest="zlib lzma" > > tiff_encoder_suggest="zlib" > > +tiff_decoder_select="mjpeg_decoder" > > truehd_decoder_select="mlp_parser" > > You should pair the new decoder line with the other decoder line, not > place it below the encoder. > > > +int is_jpeg; // 0 - Not JPEG, 1 - JPEG, 2 - New JPEG > > "is" makes this sound boolean, perhaps better "jpeg_type" or something > like that. > > OTOH, I can't find the differentiation between 1 and 2 used anywhere. > > > +// Lookup table lookup > > +if (lut) value = lut[value]; > > You probably need to break the line, according to ffmpeg coding rules. > > > +float scale_factor; > > + > > +scale_factor = 1.0 / (s->white_level - s->black_level); > > This is promoting the floating point operation to a double precision > operation (significant for some platforms). Either use double variables > in the first place - if the extra precision can be justified - or use > the "f" suffix to the constant: "1.0f". > > > +ret = avcodec_receive_frame(s->avctx_mjpeg, s->jpgframe); > > +if (ret < 0) { > > +av_log(avctx, AV_LOG_ERROR, "JPEG decoding error (%d).\n", ret); > > I believe the return value can be decoded into a string, e.g. with > av_err2str(). > > > +/* Copy the outputted tile's pixels from 'jpgframe' to to 'frame' > > (final buffer */ > > Outputted is not a word. ;-) Don't worry about that, but there's a > duplicate "to" in there, and the bracket is not closed. > > > +uint32_t lut_offset = value; > > +uint32_t lut_size = count; > > +uint32_t lut_wanted_size = 1 << s->bpp; > > +if (lut_wanted_size != lut_size) > > +av_log(s->avctx, AV_LOG_WARNING, "DNG contains LUT with > > invalid size (%d), disabling LUT\n", lut_size); > > +else if (lut_offset >= bytestream2_size(&s->gb)) > > +av_log(s->avctx, AV_LOG_WARNING, "DNG contains LUT with > > invalid offset (%d), disabling LUT\n", lut_offset); > > Nit: the proper format identifier for uint32_t is '"%" PRIu32'. ( > > > +} else { > > +av_log(avctx, AV_LOG_ERROR, "DNG JPG-compressed > > non-bayer-encoded images are not supported\n"); > > +return AVERROR_PATCHWELCOME; > > Alternatively (to av_log()) use avpriv_report_missing_feature(). > > > +} > > +} else if (s->is_tiled) { > > +av_log(avctx, AV_LOG_ERROR, "DNG uncompressed tiled images are > > not supported\n"); > > +return AVERROR_PATCHWELCOME; > > Ditto. > > > +s->jpgframe = av_frame_alloc(); > > +if (!s->jpgframe) > > +return AVERROR(ENOMEM); > > + > > +/* Prepare everything needed for JPEG decoding */ > > +codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); > > +if (!codec) > > +return AVERROR_BUG; > > +s->avctx_mjpeg = avcodec_alloc_context3(codec); > > +if (!s->avctx_mjpeg) > > +return AVERROR(ENOMEM); > > Don't you need to free s->jpgframe here? (And codec?) > > Cheers, > Moritz > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v7 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Στις Παρ, 26 Ιουλ 2019 στις 2:21 π.μ., ο/η Reimar Döffinger έγραψε: > > On 25.07.2019, at 17:35, velocit...@gmail.com wrote: > > > +// Lookup table lookup > > +if (lut) > > +value = lut[value]; > > As this function is in the innermost loop, doing the if here instead of > having 2 different implementations is likely not ideal speed-wise. If this were C++ this'd be trivial, but as it stands I don't see a way to do this without sacrificing code readability and/or size. I believe branch prediction and instruction pipelining will hide this delay. I doubt it has any measurable effect on performance. > > +// Color scaling > > +value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * > > 0x)); > > As input and output are both 16 bit I wonder if floating-point isn't rather > overkill compared to doing fixed-point arithmetic. Scaling in the [0.0, 1.0] range is mentioned in the DNG spec and it's also what dcraw does. > > > > +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_raw_to_linear16(*src_u16++, s->dng_lut, > > s->black_level, scale_factor); > > + > > +dst += dst_stride * sizeof(uint16_t); > > +src += src_stride * sizeof(uint16_t); > > Is all this casting working correctly on e.g. big-endian? Not sure, I don't see why not, considering I've seen such casting in other parts of ffmpeg. > Also using sizeof on uint16_t and uint8_t seems a bit overkill. It makes the programmer's intention clear, I think that's worth the few extra characters. > Also not sure if since these are essentially brightness/contrast adjustments > if we should't rather just have a way to export the transform to use... Export to where? I don't see why you'd need to complicate this by calling into other components, the transformation code is concise, clear and accurate for this use case. > > > @@ -1519,6 +1773,26 @@ again: > > return AVERROR_INVALIDDATA; > > } > > > > +/* Handle DNG images with JPEG-compressed tiles */ > > + > > +if (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == > > TIFF_TYPE_CINEMADNG) { > > +if (s->is_jpeg) { > > +if (s->is_bayer) { > > +if ((ret = dng_decode(avctx, (AVFrame*)data, avpkt)) > 0) > > +*got_frame = 1; > > +return ret; > > +} else { > > +avpriv_report_missing_feature(avctx, "DNG JPG-compressed > > non-bayer-encoded images"); > > +return AVERROR_PATCHWELCOME; > > +} > > +} else if (s->is_tiled) { > > +avpriv_report_missing_feature(avctx, "DNG uncompressed tiled > > images"); > > +return AVERROR_PATCHWELCOME; > > +} > > There is no need for an "else" block if the "if" block ends in a return. Indeed, but in my opinion it makes the code clearer on first glance (if you miss the return). I can change it if you insist. > Also putting the error handling first/at the deepest indentation level > results in more readable code generally. That's true, I will do that. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v7 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Στις Κυρ, 28 Ιουλ 2019 στις 1:30 π.μ., ο/η Reimar Döffinger έγραψε: > > Huh? Are you thinking of templates? always_inline can usually be used the > same way. > I haven't looked into the how or anything, it was just a comment in principle. You're totally right (I checked on godbolt just to make sure), I hadn't considered that. Would need a trivial change (plus the function is already inlined) so I'll do it. > > I believe branch prediction and instruction pipelining will hide this > > delay. I doubt it has any measurable effect on performance. > > There are CPUs without that. Yes, but with neither? Branch prediction, sure, but I'd like to hear one example of a CPU FFmpeg runs on without pipelining (I genuinely don't know if there are). > Of course would need to look at what the actual requirements are concerning > precision, rounding and range. But that should be done anyway. Like I said, I did. It's not possible :) > Well, I did not find it obvious where src and dst are from and what format > they are in. > Essentially if they are decoder output it's likely fine, if they are read > from a file without decoding step it's likely wrong. Right, I see your concern. They are read from a file and they can be both LE/BE, but that's specified in the file and there is logic in tiff.c to account for it. So when we process them they are guaranteed to be the same endianness as the host. > >> Also not sure if since these are essentially brightness/contrast > >> adjustments if we should't rather just have a way to export the transform > >> to use... > > > > Export to where? > > Just provide as metadata and leave to e.g. libavfilter. Not sure how I'd do that or if it'd be appropriate/feasible. > > I don't see why you'd need to complicate this by > > calling into other components, the transformation code is concise, > > clear and accurate for this use case. > > Slow and unoptimized and in it's current form hard to SIMD optimize, > especially without changing output as well though (in addition to the large > bit width of floats reducing the benefit, denormals can be an issue for > SIMD-accelerating float code). > Unless I miss a reason why nobody would ever want this to be faster? I'll take out the comparison which should make it faster, I'll talk with my mentor if he thinks I should use libavfilter. > >> There is no need for an "else" block if the "if" block ends in a return. > > > > Indeed, but in my opinion it makes the code clearer on first glance > > (if you miss the return). I can change it if you insist. > > The second comment was the more relevant one actually. > I only really care about finding some way to make this part a whole lot more > readable. Ok, hopefully the code I posted right after your review is readable enough. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v7 2/2] lavc/tiff: Decode embedded JPEGs in DNG images
Actually, I checked a more accurate version of my loop, and GCC optimizes away the LUT check anyway: https://godbolt.org/z/G1e1R4 As you can see it's smart enough to create 2 versions of my functions (started at L3 with a lookup and L7 without it) and it does the check outside. There's no guarantee this is happening with the actual version of course (it could be slower, or even faster if it also optimizes it through dng_blit). I could check the actual disasm in FFmpeg, but I don't think it's worth it at this point (my mentor agrees). Στις Κυρ, 28 Ιουλ 2019 στις 10:40 π.μ., ο/η Nick Renieris έγραψε: > > Στις Κυρ, 28 Ιουλ 2019 στις 1:30 π.μ., ο/η Reimar Döffinger > έγραψε: > > > > Huh? Are you thinking of templates? always_inline can usually be used the > > same way. > > I haven't looked into the how or anything, it was just a comment in > > principle. > > You're totally right (I checked on godbolt just to make sure), I > hadn't considered that. Would need a trivial change (plus the function > is already inlined) so I'll do it. > > > > I believe branch prediction and instruction pipelining will hide this > > > delay. I doubt it has any measurable effect on performance. > > > > There are CPUs without that. > > Yes, but with neither? Branch prediction, sure, but I'd like to hear > one example of a CPU FFmpeg runs on without pipelining (I genuinely > don't know if there are). > > > Of course would need to look at what the actual requirements are concerning > > precision, rounding and range. But that should be done anyway. > Like I said, I did. It's not possible :) > > > Well, I did not find it obvious where src and dst are from and what format > > they are in. > > Essentially if they are decoder output it's likely fine, if they are read > > from a file without decoding step it's likely wrong. > > Right, I see your concern. They are read from a file and they can be > both LE/BE, but that's specified in the file and there is logic in > tiff.c to account for it. So when we process them they are guaranteed > to be the same endianness as the host. > > > >> Also not sure if since these are essentially brightness/contrast > > >> adjustments if we should't rather just have a way to export the > > >> transform to use... > > > > > > Export to where? > > > > Just provide as metadata and leave to e.g. libavfilter. > > Not sure how I'd do that or if it'd be appropriate/feasible. > > > > I don't see why you'd need to complicate this by > > > calling into other components, the transformation code is concise, > > > clear and accurate for this use case. > > > > Slow and unoptimized and in it's current form hard to SIMD optimize, > > especially without changing output as well though (in addition to the large > > bit width of floats reducing the benefit, denormals can be an issue for > > SIMD-accelerating float code). > > Unless I miss a reason why nobody would ever want this to be faster? > > I'll take out the comparison which should make it faster, I'll talk > with my mentor if he thinks I should use libavfilter. > > > >> There is no need for an "else" block if the "if" block ends in a return. > > > > > > Indeed, but in my opinion it makes the code clearer on first glance > > > (if you miss the return). I can change it if you insist. > > > > The second comment was the more relevant one actually. > > I only really care about finding some way to make this part a whole lot > > more readable. > > Ok, hopefully the code I posted right after your review is readable enough. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v9 1/2] lavc/mjpegdec: Decode Huffman-coded lossless JPEGs embedded in DNGs
Going to post a new patchset with my latest work. It includes these 2 commits (one slightly modified) and 11 more. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v10 04/13] lavc/tiff: Apply color scaling to uncompressed DNGs
Thanks for the review Michael, pushing fixes and a commit that makes some more images compatible. Στις Πέμ, 8 Αυγ 2019 στις 1:22 π.μ., ο/η Michael Niedermayer έγραψε: > > On Wed, Aug 07, 2019 at 06:27:14PM +0300, velocit...@gmail.com wrote: > > From: Nick Renieris > > > > Signed-off-by: Nick Renieris > > --- > > libavcodec/tiff.c | 22 +- > > 1 file changed, 21 insertions(+), 1 deletion(-) > > > > diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c > > index c7e2adb3ae..b6f626daca 100644 > > --- a/libavcodec/tiff.c > > +++ b/libavcodec/tiff.c > > @@ -679,6 +679,25 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame > > *p, uint8_t *dst, int strid > > for (i = 0; i < width; i++) > > dst[i] = ff_reverse[src[i]]; > > } > > + > > +/* Color processing for DNG images with uncompressed strips > > (non-tiled) */ > > +if (is_dng) { > > This variable is only added in a later patch > so this does not build > > also some change in this patchset breaks: > ./ffplay tickets/2826/pred6disc7.jpg > file should be here: > https://trac.ffmpeg.org/raw-attachment/ticket/2826/pred6disc7.jpg > > Thanks > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > Does the universe only have a finite lifespan? No, its going to go on > forever, its just that you wont like living in it. -- Hiranya Peiri > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 01/14] lavc/mjpegdec: Decode Huffman-coded lossless JPEGs embedded in DNGs
From: Nick Renieris Main image data in DNGs is usually comprised of tiles, each of which is a Huffman-encoded lossless JPEG. Tested for ljpeg regressions with: `ffmpeg -f lavfi -i testsrc=d=1 -vcodec ljpeg test.avi` `ffmpeg test.avi out.avi` The modified code in ljpeg_decode_rgb_scan runs without issues. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 52 +-- libavcodec/mjpegdec.h | 1 + 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index a65bc8df15..6391107f78 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,6 +412,14 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } +/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 + interleaved components and the width stored in their SOF3 markers is the + width of each one. We only output a single component, therefore we need + to adjust the output image width. */ +if (s->lossless == 1 && nb_components == 2) { +s->bayer = 1; +width *= 2; +} /* if different size, realloc/alloc picture */ if (width != s->width || height != s->height || bits != s->bits || @@ -488,6 +496,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } switch (pix_fmt_id) { +case 0x: /* for bayer-encoded huffman lossless JPEGs embedded in DNGs */ +s->avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; +break; case 0x1100: if (s->rgb) s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48; @@ -1041,17 +1052,20 @@ static int handle_rstn(MJpegDecodeContext *s, int nb_components) return reset; } +/* Handles 1 to 4 components */ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform) { int i, mb_x, mb_y; +unsigned width; uint16_t (*buffer)[4]; int left[4], top[4], topleft[4]; const int linesize = s->linesize[0]; const int mask = ((1 << s->bits) - 1) << point_transform; int resync_mb_y = 0; int resync_mb_x = 0; +int vpred[6]; -if (s->nb_components != 3 && s->nb_components != 4) +if (s->nb_components <= 0 || s->nb_components > 4) return AVERROR_INVALIDDATA; if (s->v_max != 1 || s->h_max != 1 || !s->lossless) return AVERROR_INVALIDDATA; @@ -1059,8 +1073,15 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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])); +if (s->restart_interval == 0) +s->restart_interval = INT_MAX; + +if (s->bayer) +width = s->mb_width / nb_components; /* Interleaved, width stored is the total so need to divide */ +else +width = s->mb_width; + +av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, width * 4 * sizeof(s->ljpeg_buffer[0][0])); if (!s->ljpeg_buffer) return AVERROR(ENOMEM); @@ -1078,7 +1099,12 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 ((mb_y * s->width) % s->restart_interval == 0) { +for (i = 0; i < 6; i++) +vpred[i] = 1 << (s->bits-1); +} + +for (mb_x = 0; mb_x < width; mb_x++) { int modified_predictor = predictor; if (get_bits_left(&s->gb) < 1) { @@ -1102,12 +1128,19 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 == 0xF) return -1; +if (!s->bayer || mb_x) { +pred = left[i]; +} else { /* This path runs only for the first line in bayer images */ +vpred[i] += dc; +pred = vpred[i] - dc; +} + +PREDICT(pred, topleft[i], top[i], pred, modified_predictor); + left[i] = buffer[mb_x][i] = mask & (pred + (unsigned)(dc * (1 << point_transform))); } @@ -1151,6 +1184,11 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p ptr[
[FFmpeg-devel] [PATCH v12 10/14] lavc/tiff: Support decoding of DNGs with single-component JPEGs
From: Nick Renieris 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 --- libavcodec/tiff.c | 61 +++ 1 file changed, 51 insertions(+), 10 deletions(-) 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(AVCod
[FFmpeg-devel] [PATCH v12 05/14] lavc/jpegtables: Handle multiple mappings to the same value
From: Nick Renieris Some JPEGs [1] have incorrect DHT entries that map 2 codes to the same value. The second (last) mapping does not ever actually appear in the code stream, therefore ignoring any mappings after the first one fixes this. Without this, an "mjpeg_decode_dc: bad vlc: 0:0" error is thrown. --- [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/jpegtables.c | 19 --- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index cbe5523cb4..6f596cfc92 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -130,14 +130,27 @@ void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, { int i, j, k,nb, code, sym; -code = 0; +/* Zero-initialize huff_size (needed for multiple mappings check below) */ +k = 0; +for(i=1;i<=16;i++) { +nb = bits_table[i]; +for(j=0;jhttps://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 06/14] lavc/tiff: Fix edge case with full-length/width tiles
From: Nick Renieris In an image [1], the height was equal to the tile length (full-height tile) and after `height % tile_length` was applied to them with the current code, it resulted in the operating tile_length to be 0. This commit makes this leftover logic only applies if it's necessary. Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 4620508d53..37fda15162 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -887,10 +887,14 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int tile_byte_count_offset, tile_byte_count; int tile_count_x, tile_count_y; int tile_width, tile_length; +int has_width_leftover, has_height_leftover; int tile_x = 0, tile_y = 0; int pos_x = 0, pos_y = 0; int ret; +has_width_leftover = (s->width % s->tile_width != 0); +has_height_leftover = (s->height % s->tile_length != 0); + /* Calculate tile counts (round up) */ tile_count_x = (s->width + s->tile_width - 1) / s->tile_width; tile_count_y = (s->height + s->tile_length - 1) / s->tile_length; @@ -900,12 +904,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) tile_x = tile_idx % tile_count_x; tile_y = tile_idx / tile_count_x; -if (tile_x == tile_count_x - 1) // If on the right edge +if (has_width_leftover && tile_x == tile_count_x - 1) // If on the right-most tile tile_width = s->width % s->tile_width; else tile_width = s->tile_width; -if (tile_y == tile_count_y - 1) // If on the bottom edge +if (has_height_leftover && tile_y == tile_count_y - 1) // If on the bottom-most tile tile_length = s->height % s->tile_length; else tile_length = s->tile_length; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 08/14] lavc/tiff: Force DNG pixel data endianness on an edge case
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 12 1 file changed, 12 insertions(+) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 174ca168c6..9d20763186 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1038,6 +1038,18 @@ static int init_image(TiffContext *s, ThreadFrame *frame) AV_RL32(s->pattern)); return AVERROR_PATCHWELCOME; } +/* Force endianness as mentioned in 'DNG Specification: Chapter 3: BitsPerSample' +NOTE: The spec actually specifies big-endian, not sure why we need little-endian, + but such images don't work otherwise. */ +if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) +&& (s->bpp != 8 && s->bpp != 16 && s->bpp != 32)) { +switch (s->avctx->pix_fmt) { +case AV_PIX_FMT_BAYER_RGGB16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE; break; +case AV_PIX_FMT_BAYER_BGGR16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16LE; break; +case AV_PIX_FMT_BAYER_GBRG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE; break; +case AV_PIX_FMT_BAYER_GRBG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16LE; break; +} +} break; case 10161: switch (AV_RL32(s->pattern)) { -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 07/14] lavc/tiff: Don't apply strips-related logic to tiled images
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 42 ++ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 37fda15162..174ca168c6 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1780,7 +1780,7 @@ again: } } -if (!s->strippos && !s->stripoff) { +if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } @@ -1788,27 +1788,29 @@ again: if ((ret = init_image(s, &frame)) < 0) return ret; -if (s->strips == 1 && !s->stripsize) { -av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); -s->stripsize = avpkt->size - s->stripoff; -} +if (!s->is_tiled) { +if (s->strips == 1 && !s->stripsize) { +av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); +s->stripsize = avpkt->size - s->stripoff; +} -if (s->stripsizesoff) { -if (s->stripsizesoff >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, - avpkt->size - s->stripsizesoff); -} -if (s->strippos) { -if (s->strippos >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripdata, avpkt->data + s->strippos, - avpkt->size - s->strippos); -} +if (s->stripsizesoff) { +if (s->stripsizesoff >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, +avpkt->size - s->stripsizesoff); +} +if (s->strippos) { +if (s->strippos >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripdata, avpkt->data + s->strippos, +avpkt->size - s->strippos); +} -if (s->rps <= 0 || s->rps % s->subsampling[1]) { -av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); -return AVERROR_INVALIDDATA; +if (s->rps <= 0 || s->rps % s->subsampling[1]) { +av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); +return AVERROR_INVALIDDATA; +} } /* Handle DNG images with JPEG-compressed tiles */ -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 12/14] lavc/mjpegdec: Skip useless APPx marker on bayer images
From: Nick Renieris Samples: - Embedded JPEG images in the DNG images here: https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 0a920a7144..e7b273a363 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1807,8 +1807,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) int len, id, i; len = get_bits(&s->gb, 16); -if (len < 6) -return AVERROR_INVALIDDATA; +if (len < 6) { +if (s->bayer) { +// Pentax K-1 (digital camera) JPEG images embedded in DNG images contain useless APP0 markers +av_log(s->avctx, AV_LOG_WARNING, "skipping APPx (len=%"PRId32") for bayer-encoded image\n", len); +skip_bits(&s->gb, len); +return 0; +} else +return AVERROR_INVALIDDATA; +} if (8 * len > get_bits_left(&s->gb)) return AVERROR_INVALIDDATA; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 14/14] lavc/tiff: Initialize WhiteLevel DNG tag value
From: Nick Renieris Inited to (2^BitsPerSample)-1 as per the DNG Specification This fixes decoding for "X7 CinemaDNG" samples here: - https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 13 ++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index b9aa4efd02..aeb80a70a9 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1773,6 +1773,7 @@ static int decode_frame(AVCodecContext *avctx, GetByteContext stripsizes; GetByteContext stripdata; int retry_for_subifd, retry_for_page; +int is_dng; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -1841,6 +1842,10 @@ again: goto again; } +/* At this point we've decided on which (Sub)IFD to process */ + +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (i = 0; igeotag_count; i++) { const char *keyname = get_geokey_name(s->geotags[i].key); if (!keyname) { @@ -1858,10 +1863,13 @@ again: } } +s->white_level = (1 << s->bpp) - 1; /* Default value as per the spec */ + if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } + /* now we have the data and may start decoding */ if ((ret = init_image(s, &frame)) < 0) return ret; @@ -1893,7 +1901,7 @@ again: /* Handle DNG images with JPEG-compressed tiles */ -if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) && s->is_tiled) { +if (is_dng && s->is_tiled) { if (!s->is_jpeg) { avpriv_report_missing_feature(avctx, "DNG uncompressed tiled images"); return AVERROR_PATCHWELCOME; @@ -2051,8 +2059,7 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16 && -!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { +if (s->is_bayer && s->bpp == 16 && !is_dng && (s->white_level != (1 << s->bpp) - 1)) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 11/14] lavc/tiff: Decode 14-bit DNG images
From: Nick Renieris Sample file: https://drive.google.com/open?id=0B4JyRT3Lth5HVndyOTVOdWktM3J4TFEydTk1MnY3RWlpSzVB Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index ecd87c0b2f..0d931641c2 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -309,14 +309,18 @@ static void av_always_inline horizontal_fill(TiffContext *s, dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; } break; -case 12: { - uint16_t *dst16 = (uint16_t *)dst; - GetBitContext gb; - init_get_bits8(&gb, src, width); - for (int i = 0; i < s->width; i++) { - dst16[i] = get_bits(&gb, 12) << 4; - } - } +case 12: +case 14: { +uint16_t *dst16 = (uint16_t *)dst; +int is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +uint8_t shift = is_dng ? 0 : 16 - bpp; +GetBitContext gb; + +init_get_bits8(&gb, src, width); +for (int i = 0; i < s->width; i++) { +dst16[i] = get_bits(&gb, bpp) << shift; +} +} break; default: if (usePtr) { @@ -1068,6 +1072,7 @@ static int init_image(TiffContext *s, ThreadFrame *frame) } break; case 10121: +case 10141: switch (AV_RL32(s->pattern)) { case 0x02010100: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 02/14] lavc/tiff: Decode embedded JPEGs in DNG images
From: Nick Renieris Used a technique similar to lavc/tdsc.c for invoking the MJPEG decoder. This commit adds support for: - DNG tiles - DNG tile huffman lossless JPEG decoding - DNG 8-bpp ("packed" as dcraw calls it) decoding - DNG color scaling [1] - LinearizationTable tag - BlackLevel tag [1]: As specified in the DNG Specification - Chapter 5 Signed-off-by: Nick Renieris --- configure | 1 + libavcodec/Makefile | 2 +- libavcodec/tiff.c | 315 +++- libavcodec/tiff.h | 2 + 4 files changed, 312 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 34c2adb4a4..112b84f0ba 100755 --- a/configure +++ b/configure @@ -2817,6 +2817,7 @@ tdsc_decoder_deps="zlib" tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" +tiff_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib lzma" tiff_encoder_suggest="zlib" truehd_decoder_select="mlp_parser" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3cd73fbcc6..f814c69996 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -616,7 +616,7 @@ OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o OBJS-$(CONFIG_TDSC_DECODER)+= tdsc.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o -OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o +OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o mjpegdec.o OBJS-$(CONFIG_TIFF_ENCODER)+= tiffenc.o rle.o lzwenc.o tiff_data.o OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index c520d7df83..d5673abb19 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -35,6 +35,7 @@ #include "libavutil/attributes.h" #include "libavutil/avstring.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +47,7 @@ #include "mathops.h" #include "tiff.h" #include "tiff_data.h" +#include "mjpegdec.h" #include "thread.h" #include "get_bits.h" @@ -54,6 +56,10 @@ typedef struct TiffContext { AVCodecContext *avctx; GetByteContext gb; +/* JPEG decoding for DNG */ +AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG +AVFrame *jpgframe; // decoded JPEG tile + int get_subimage; uint16_t get_page; int get_thumbnail; @@ -76,7 +82,9 @@ typedef struct TiffContext { int is_bayer; uint8_t pattern[4]; +unsigned black_level; unsigned white_level; +const uint16_t *dng_lut; // Pointer to DNG linearization table uint32_t sub_ifd; uint16_t cur_page; @@ -86,6 +94,14 @@ typedef struct TiffContext { int stripsizesoff, stripsize, stripoff, strippos; LZWState *lzw; +/* Tile support */ +int is_tiled; +int tile_byte_counts_offset, tile_offsets_offset; +int tile_width, tile_length; +int tile_count; + +int is_jpeg; + uint8_t *deinvert_buf; int deinvert_buf_size; uint8_t *yuv_line; @@ -257,6 +273,9 @@ 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); + static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, int usePtr, const uint8_t *src, @@ -712,6 +731,204 @@ 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_raw_to_linear16(uint16_t value, +const uint16_t *lut, +uint16_t black_level, +float scale_factor) { +// Lookup table lookup +if (lut) +value = lut[value]; + +// Black level subtraction +value = av_clip_uint16_c((unsigned)value - black_level); + +// Color scaling +value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); + +return value; +} + +static uint16_t av_always_inline dng_raw_to_linear8(uint16_t value, +const uint16_t *lut, +uint1
[FFmpeg-devel] [PATCH v12 03/14] lavc/tiff: Convert DNGs to sRGB color space
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 34 +++--- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index d5673abb19..a118c37c41 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -731,14 +731,23 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid return 0; } +static float av_always_inline linear_to_srgb(float value) { +if (value <= 0.0031308) +return value * 12.92; +else +return pow(value * 1.055, 1.0 / 2.4) - 0.055; +} + /** - * Map stored raw sensor values into linear reference values. - * See: DNG Specification - Chapter 5 + * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5) + * Then convert to sRGB color space. */ -static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, -const uint16_t *lut, -uint16_t black_level, -float scale_factor) { +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]; @@ -747,16 +756,19 @@ static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, value = av_clip_uint16_c((unsigned)value - black_level); // Color scaling -value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); +value_norm = (float)value * scale_factor; + +// Color space conversion (sRGB) +value = av_clip_uint16_c((uint16_t)(linear_to_srgb(value_norm) * 0x)); return value; } -static uint16_t av_always_inline dng_raw_to_linear8(uint16_t 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_raw_to_linear16(value, lut, black_level, scale_factor) >> 8; +return dng_process_color16(value, lut, black_level, scale_factor) >> 8; } static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, @@ -774,7 +786,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, uint16_t *src_u16 = (uint16_t *)src; for (col = 0; col < width; col++) -*dst_u16++ = dng_raw_to_linear16(*src_u16++, s->dng_lut, s->black_level, scale_factor); +*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); @@ -782,7 +794,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } else { for (line = 0; line < height; line++) { for (col = 0; col < width; col++) -*dst++ = dng_raw_to_linear8(*src++, s->dng_lut, s->black_level, scale_factor); +*dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); dst += dst_stride; src += src_stride; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 09/14] lavc/mjpegdec: Enable decoding of single-component bayer images
From: Nick Renieris Also, ensure no false positives when determining DNG bayer images, by setting them in tiff.c instead of relying on a heuristic. There's no way to determine this just from the JPEG data, so we have to pass this information from outside the MJPEG decoder. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 32 +--- libavcodec/tiff.c | 7 +++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 6391107f78..0a920a7144 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,13 +412,17 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } -/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 - interleaved components and the width stored in their SOF3 markers is the - width of each one. We only output a single component, therefore we need - to adjust the output image width. */ -if (s->lossless == 1 && nb_components == 2) { -s->bayer = 1; -width *= 2; +if (s->bayer) { +if (nb_components == 2) { +/* Bayer images embedded in DNGs can contain 2 interleaved components and the + width stored in their SOF3 markers is the width of each one. We only output + a single component, therefore we need to adjust the output image width. We + handle the deinterleaving (but not the debayering) in this file. */ +width *= 2; +} +/* They can also contain 1 component, which is double the width and half the height +of the final image (rows are interleaved). We don't handle the decoding in this +file, but leave that to the TIFF/DNG decoder. */ } /* if different size, realloc/alloc picture */ @@ -1184,10 +1188,16 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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->bayer && nb_components == 2) { -for (mb_x = 0; mb_x < width; mb_x++) { -((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; -((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} else if (s->bayer) { +if (nb_components == 1) { +/* Leave decoding to the TIFF/DNG decoder (see comment in ff_mjpeg_decode_sof) */ +for (mb_x = 0; mb_x < width; mb_x++) +((uint16_t*)ptr)[mb_x] = buffer[mb_x][0]; +} else if (nb_components == 2) { +for (mb_x = 0; mb_x < width; mb_x++) { +((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; +((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} } } else { for(i=0; igb.buffer; 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, &jpkt); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 04/14] lavc/tiff: Apply color scaling to uncompressed DNGs
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index a118c37c41..4620508d53 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -556,6 +556,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; +int is_dng; if (s->planar) width /= s->bppcount; @@ -657,6 +658,8 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid bytestream2_init(&s->gb, src, size); bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -679,6 +682,25 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid for (i = 0; i < width; i++) dst[i] = ff_reverse[src[i]]; } + +/* Color processing for DNG images with uncompressed strips (non-tiled) */ +if (is_dng) { +int is_u16, pixel_size_bytes, pixel_size_bits; + +is_u16 = (s->bpp > 8); +pixel_size_bits = (is_u16 ? 16 : 8); +pixel_size_bytes = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + +dng_blit(s, + dst, + 0, // no stride, only 1 line + dst, + 0, // no stride, only 1 line + width / pixel_size_bytes * pixel_size_bits / s->bpp, // need to account for [1, 16] bpp + 1, + is_u16); +} + src += width; break; case TIFF_PACKBITS: @@ -1947,7 +1969,8 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16) { +if (s->is_bayer && s->white_level && s->bpp == 16 && +!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v12 13/14] lavc/tiff: Support DNGs with striped (non-tiled) JPEGs images
From: Nick Renieris DNG samples here can now be decoded: - https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 73 +++ 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 0d931641c2..b9aa4efd02 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -550,6 +550,8 @@ 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 tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -665,6 +667,17 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +/* Decode JPEG-encoded DNGs with strips */ +if (s->compr == TIFF_NEWJPEG && is_dng) { +if (s->strips > 1) { +av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); +return AVERROR_PATCHWELCOME; +} +if ((ret = dng_decode_strip(s->avctx, p)) < 0) +return ret; +return 0; +} + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -859,8 +872,8 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } } -static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, -int tile_byte_count, int x, int y, int w, int h) +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; AVPacket jpkt; @@ -912,7 +925,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return AVERROR_PATCHWELCOME; } -dst_offset = x + frame->linesize[0] * y / pixel_size; +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]; @@ -931,7 +944,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) +static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { TiffContext *s = avctx->priv_data; int tile_idx; @@ -944,6 +957,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int pos_x = 0, pos_y = 0; int ret; +s->jpgframe->width = s->tile_width; +s->jpgframe->height = s->tile_length; + +s->avctx_mjpeg->width = s->tile_width; +s->avctx_mjpeg->height = s->tile_length; + has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); @@ -980,7 +999,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) bytestream2_seek(&s->gb, tile_offset, SEEK_SET); /* Decode JPEG tile and copy it in the reference frame */ -ret = dng_decode_jpeg_tile(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); +ret = dng_decode_jpeg(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); if (ret < 0) return ret; @@ -993,30 +1012,24 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) } } -return 0; -} +/* Frame is ready to be output */ +frame->pict_type = AV_PICTURE_TYPE_I; +frame->key_frame = 1; -static int dng_decode(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { -int ret; +return avpkt->size; +} +static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) +{ TiffContext *s = avctx->priv_data; -s->jpgframe->width = s->tile_width; -s->jpgframe->height = s->tile_length; - -s->avctx_mjpeg->width = s->tile_width; -s->avctx_mjpeg->height = s->tile_length; - -/* Decode all tiles in a frame */ -ret = dng_decode_tiles(avctx, frame); -if (ret < 0) -return ret; +s->jpgframe->width = s->width; +s->jpgframe->height = s->height; -/* Frame is ready to be output */ -frame->pict_type = AV_PICTURE_TYPE_I; -frame->key_frame = 1; +s->avctx_mjpeg->width = s->width; +s->avctx_mjpeg->height = s->height; -return avpkt->size; +return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); } static int ini
Re: [FFmpeg-devel] [PATCH v12 03/14] lavc/tiff: Convert DNGs to sRGB color space
> Why do you put all this color space convertion code into the decoders ? The color space conversion needs to happen, camera sensor data is linear. If it's not done images looks really dark as result. > Colorspace and pixel format convertion is generally done outside decoders. > The specification cannot specify what part of FFmpeg's code does the conversion. I had found some sRGB conversion code in libswscale, asked about using it and was told not to. It's only 4 simple lines, as opposed to probably more complicated code to use libswscale or whatever. Στις Σάβ, 10 Αυγ 2019 στις 4:43 μ.μ., ο/η Nicolas George έγραψε: > > Paul B Mahol (12019-08-10): > > It is part of DNG specification. Do you want to not follow DNG > > specification? > > The specification cannot specify what part of FFmpeg's code does the > conversion. > > -- > Nicolas George > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v12 05/14] lavc/jpegtables: Handle multiple mappings to the same value
I haven't seen any files with sym!=0, just thought I'd solve the general case. I'll change only for sym==0. Can always be changed later if any such samples are found. Στις Σάβ, 10 Αυγ 2019 στις 4:11 μ.μ., ο/η Michael Niedermayer έγραψε: > > On Fri, Aug 09, 2019 at 07:29:50PM +0300, Nick Renieris wrote: > > From: Nick Renieris > > > > Some JPEGs [1] have incorrect DHT entries that map 2 codes to > > the same value. > > > > The second (last) mapping does not ever actually appear in the > > code stream, therefore ignoring any mappings after the first one > > fixes this. > > > > Without this, an "mjpeg_decode_dc: bad vlc: 0:0" error is thrown. > > > > --- > > > > [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: > > https://www.dji.com/gr/zenmuse-x7/info#downloads > > > > Signed-off-by: Nick Renieris > > --- > > libavcodec/jpegtables.c | 19 --- > > 1 file changed, 16 insertions(+), 3 deletions(-) > > > > diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c > > index cbe5523cb4..6f596cfc92 100644 > > --- a/libavcodec/jpegtables.c > > +++ b/libavcodec/jpegtables.c > > @@ -130,14 +130,27 @@ void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, > > uint16_t *huff_code, > > { > > int i, j, k,nb, code, sym; > > > > -code = 0; > > +/* Zero-initialize huff_size (needed for multiple mappings check > > below) */ > > +k = 0; > > +for(i=1;i<=16;i++) { > > +nb = bits_table[i]; > > +for(j=0;j > +sym = val_table[k++]; > > +huff_size[sym] = 0; > > +} > > +} > > + > > k = 0; > > +code = 0; > > for(i=1;i<=16;i++) { > > nb = bits_table[i]; > > for(j=0;j > sym = val_table[k++]; > > -huff_size[sym] = i; > > -huff_code[sym] = code; > > +/* If there are multiple mappings to the same sym (bad files), > > keep the first code */ > > +if (huff_size[sym] == 0) { > > +huff_size[sym] = i; > > +huff_code[sym] = code; > > +} > > do these occur with sym different from 0 ? > if its just 0 then this can be simplified alot > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > I do not agree with what you have to say, but I'll defend to the death your > right to say it. -- Voltaire > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v12 12/14] lavc/mjpegdec: Skip useless APPx marker on bayer images
The data the marker contains is only 2 bytes and they're 0x in the samples above. I don't know what they're for. Στις Σάβ, 10 Αυγ 2019 στις 3:16 μ.μ., ο/η Michael Niedermayer έγραψε: > > On Fri, Aug 09, 2019 at 07:29:57PM +0300, Nick Renieris wrote: > > From: Nick Renieris > > > > Samples: > > - Embedded JPEG images in the DNG images here: > > https://www.photographyblog.com/previews/pentax_k1_photos > > > > Signed-off-by: Nick Renieris > > --- > > libavcodec/mjpegdec.c | 11 +-- > > 1 file changed, 9 insertions(+), 2 deletions(-) > > > > diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c > > index 0a920a7144..e7b273a363 100644 > > --- a/libavcodec/mjpegdec.c > > +++ b/libavcodec/mjpegdec.c > > @@ -1807,8 +1807,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) > > int len, id, i; > > > > len = get_bits(&s->gb, 16); > > -if (len < 6) > > -return AVERROR_INVALIDDATA; > > +if (len < 6) { > > +if (s->bayer) { > > +// Pentax K-1 (digital camera) JPEG images embedded in DNG > > images contain useless APP0 markers > > "useless" is a quite generic term, is it known what the contain why they > are there ? > > thx > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > Asymptotically faster algorithms should always be preferred if you have > asymptotical amounts of data > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v12 01/14] lavc/mjpegdec: Decode Huffman-coded lossless JPEGs embedded in DNGs
I assume you're talking about the "if (!s->bayer || mb_x) {"... code. 1) The special case there happens for the first line, not row like the code you mentioned. 2) The loop is "width*height*component" in this order, so I'm not sure how I would something for the first line outside. 3) It depends on mjpeg_decode_dc being called for the first-line case, I'm not sure how I'd handle that either (even just to take it outside the "component" loop). Στις Σάβ, 10 Αυγ 2019 στις 3:30 μ.μ., ο/η Michael Niedermayer έγραψε: > > On Fri, Aug 09, 2019 at 07:29:46PM +0300, Nick Renieris wrote: > > From: Nick Renieris > > > > Main image data in DNGs is usually comprised of tiles, each of which is a > > Huffman-encoded lossless JPEG. > > > > Tested for ljpeg regressions with: > > `ffmpeg -f lavfi -i testsrc=d=1 -vcodec ljpeg test.avi` > > `ffmpeg test.avi out.avi` > > The modified code in ljpeg_decode_rgb_scan runs without issues. > > > > Signed-off-by: Nick Renieris > > --- > > libavcodec/mjpegdec.c | 52 +-- > > libavcodec/mjpegdec.h | 1 + > > 2 files changed, 46 insertions(+), 7 deletions(-) > [...] > > > @@ -1102,12 +1128,19 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext > > *s, int nb_components, int p > > 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 == 0xF) > > return -1; > > > > +if (!s->bayer || mb_x) { > > +pred = left[i]; > > +} else { /* This path runs only for the first line in > > bayer images */ > > +vpred[i] += dc; > > +pred = vpred[i] - dc; > > +} > > + > > +PREDICT(pred, topleft[i], top[i], pred, > > modified_predictor); > > + > > left[i] = buffer[mb_x][i] = > > mask & (pred + (unsigned)(dc * (1 << > > point_transform))); > > } > > This should be done outside the width*height sample loop > The special handling of the left pixel for other ljpeg is also done > outside that loop > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > What does censorship reveal? It reveals fear. -- Julian Assange > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v12 10/14] lavc/tiff: Support decoding of DNGs with single-component JPEGs
> 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. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 01/14] lavc/mjpegdec: Decode Huffman-coded lossless JPEGs embedded in DNGs
From: Nick Renieris Main image data in DNGs is usually comprised of tiles, each of which is a Huffman-encoded lossless JPEG. Tested for ljpeg regressions with: `ffmpeg -f lavfi -i testsrc=d=1 -vcodec ljpeg test.avi` `ffmpeg test.avi out.avi` The modified code in ljpeg_decode_rgb_scan runs without issues. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 52 +-- libavcodec/mjpegdec.h | 1 + 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index a65bc8df15..6391107f78 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,6 +412,14 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } +/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 + interleaved components and the width stored in their SOF3 markers is the + width of each one. We only output a single component, therefore we need + to adjust the output image width. */ +if (s->lossless == 1 && nb_components == 2) { +s->bayer = 1; +width *= 2; +} /* if different size, realloc/alloc picture */ if (width != s->width || height != s->height || bits != s->bits || @@ -488,6 +496,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } switch (pix_fmt_id) { +case 0x: /* for bayer-encoded huffman lossless JPEGs embedded in DNGs */ +s->avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; +break; case 0x1100: if (s->rgb) s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48; @@ -1041,17 +1052,20 @@ static int handle_rstn(MJpegDecodeContext *s, int nb_components) return reset; } +/* Handles 1 to 4 components */ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform) { int i, mb_x, mb_y; +unsigned width; uint16_t (*buffer)[4]; int left[4], top[4], topleft[4]; const int linesize = s->linesize[0]; const int mask = ((1 << s->bits) - 1) << point_transform; int resync_mb_y = 0; int resync_mb_x = 0; +int vpred[6]; -if (s->nb_components != 3 && s->nb_components != 4) +if (s->nb_components <= 0 || s->nb_components > 4) return AVERROR_INVALIDDATA; if (s->v_max != 1 || s->h_max != 1 || !s->lossless) return AVERROR_INVALIDDATA; @@ -1059,8 +1073,15 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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])); +if (s->restart_interval == 0) +s->restart_interval = INT_MAX; + +if (s->bayer) +width = s->mb_width / nb_components; /* Interleaved, width stored is the total so need to divide */ +else +width = s->mb_width; + +av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, width * 4 * sizeof(s->ljpeg_buffer[0][0])); if (!s->ljpeg_buffer) return AVERROR(ENOMEM); @@ -1078,7 +1099,12 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 ((mb_y * s->width) % s->restart_interval == 0) { +for (i = 0; i < 6; i++) +vpred[i] = 1 << (s->bits-1); +} + +for (mb_x = 0; mb_x < width; mb_x++) { int modified_predictor = predictor; if (get_bits_left(&s->gb) < 1) { @@ -1102,12 +1128,19 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 == 0xF) return -1; +if (!s->bayer || mb_x) { +pred = left[i]; +} else { /* This path runs only for the first line in bayer images */ +vpred[i] += dc; +pred = vpred[i] - dc; +} + +PREDICT(pred, topleft[i], top[i], pred, modified_predictor); + left[i] = buffer[mb_x][i] = mask & (pred + (unsigned)(dc * (1 << point_transform))); } @@ -1151,6 +1184,11 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p ptr[
[FFmpeg-devel] [PATCH v13 02/14] lavc/tiff: Decode embedded JPEGs in DNG images
From: Nick Renieris Used a technique similar to lavc/tdsc.c for invoking the MJPEG decoder. This commit adds support for: - DNG tiles - DNG tile huffman lossless JPEG decoding - DNG 8-bpp ("packed" as dcraw calls it) decoding - DNG color scaling [1] - LinearizationTable tag - BlackLevel tag [1]: As specified in the DNG Specification - Chapter 5 Signed-off-by: Nick Renieris --- configure | 1 + libavcodec/Makefile | 2 +- libavcodec/tiff.c | 315 +++- libavcodec/tiff.h | 2 + 4 files changed, 312 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 34c2adb4a4..112b84f0ba 100755 --- a/configure +++ b/configure @@ -2817,6 +2817,7 @@ tdsc_decoder_deps="zlib" tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" +tiff_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib lzma" tiff_encoder_suggest="zlib" truehd_decoder_select="mlp_parser" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3cd73fbcc6..f814c69996 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -616,7 +616,7 @@ OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o OBJS-$(CONFIG_TDSC_DECODER)+= tdsc.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o -OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o +OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o mjpegdec.o OBJS-$(CONFIG_TIFF_ENCODER)+= tiffenc.o rle.o lzwenc.o tiff_data.o OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index c520d7df83..d5673abb19 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -35,6 +35,7 @@ #include "libavutil/attributes.h" #include "libavutil/avstring.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +47,7 @@ #include "mathops.h" #include "tiff.h" #include "tiff_data.h" +#include "mjpegdec.h" #include "thread.h" #include "get_bits.h" @@ -54,6 +56,10 @@ typedef struct TiffContext { AVCodecContext *avctx; GetByteContext gb; +/* JPEG decoding for DNG */ +AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG +AVFrame *jpgframe; // decoded JPEG tile + int get_subimage; uint16_t get_page; int get_thumbnail; @@ -76,7 +82,9 @@ typedef struct TiffContext { int is_bayer; uint8_t pattern[4]; +unsigned black_level; unsigned white_level; +const uint16_t *dng_lut; // Pointer to DNG linearization table uint32_t sub_ifd; uint16_t cur_page; @@ -86,6 +94,14 @@ typedef struct TiffContext { int stripsizesoff, stripsize, stripoff, strippos; LZWState *lzw; +/* Tile support */ +int is_tiled; +int tile_byte_counts_offset, tile_offsets_offset; +int tile_width, tile_length; +int tile_count; + +int is_jpeg; + uint8_t *deinvert_buf; int deinvert_buf_size; uint8_t *yuv_line; @@ -257,6 +273,9 @@ 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); + static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, int usePtr, const uint8_t *src, @@ -712,6 +731,204 @@ 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_raw_to_linear16(uint16_t value, +const uint16_t *lut, +uint16_t black_level, +float scale_factor) { +// Lookup table lookup +if (lut) +value = lut[value]; + +// Black level subtraction +value = av_clip_uint16_c((unsigned)value - black_level); + +// Color scaling +value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); + +return value; +} + +static uint16_t av_always_inline dng_raw_to_linear8(uint16_t value, +const uint16_t *lut, +uint1
[FFmpeg-devel] [PATCH v13 03/14] lavc/tiff: Convert DNGs to sRGB color space
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 34 +++--- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index d5673abb19..a118c37c41 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -731,14 +731,23 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid return 0; } +static float av_always_inline linear_to_srgb(float value) { +if (value <= 0.0031308) +return value * 12.92; +else +return pow(value * 1.055, 1.0 / 2.4) - 0.055; +} + /** - * Map stored raw sensor values into linear reference values. - * See: DNG Specification - Chapter 5 + * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5) + * Then convert to sRGB color space. */ -static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, -const uint16_t *lut, -uint16_t black_level, -float scale_factor) { +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]; @@ -747,16 +756,19 @@ static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, value = av_clip_uint16_c((unsigned)value - black_level); // Color scaling -value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); +value_norm = (float)value * scale_factor; + +// Color space conversion (sRGB) +value = av_clip_uint16_c((uint16_t)(linear_to_srgb(value_norm) * 0x)); return value; } -static uint16_t av_always_inline dng_raw_to_linear8(uint16_t 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_raw_to_linear16(value, lut, black_level, scale_factor) >> 8; +return dng_process_color16(value, lut, black_level, scale_factor) >> 8; } static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, @@ -774,7 +786,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, uint16_t *src_u16 = (uint16_t *)src; for (col = 0; col < width; col++) -*dst_u16++ = dng_raw_to_linear16(*src_u16++, s->dng_lut, s->black_level, scale_factor); +*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); @@ -782,7 +794,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } else { for (line = 0; line < height; line++) { for (col = 0; col < width; col++) -*dst++ = dng_raw_to_linear8(*src++, s->dng_lut, s->black_level, scale_factor); +*dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); dst += dst_stride; src += src_stride; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 05/14] lavc/jpegtables: Handle multiple mappings to the same value
From: Nick Renieris Some JPEGs [1] have incorrect DHT entries that map 2 codes to the same value. The second (last) mapping does not ever actually appear in the code stream, therefore ignoring any mappings after the first one fixes this. Without this, an "mjpeg_decode_dc: bad vlc: 0:0" error is thrown. In all known files, the 2 codes are mapped to symbol 0 so only that case is checked. --- [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/jpegtables.c | 17 ++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index cbe5523cb4..fa5c6f9fc5 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -130,14 +130,25 @@ void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, { int i, j, k,nb, code, sym; -code = 0; +/* Some badly encoded files [1] map 2 different codes to symbol 0. + Only the first one is valid, so we zero-initialize this here and + make sure we only set it once (the first time) in the loop below. + + [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: +https://www.dji.com/gr/zenmuse-x7/info#downloads + */ +huff_size[0] = 0; + k = 0; +code = 0; for(i=1;i<=16;i++) { nb = bits_table[i]; for(j=0;jhttps://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 04/14] lavc/tiff: Apply color scaling to uncompressed DNGs
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index a118c37c41..4620508d53 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -556,6 +556,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; +int is_dng; if (s->planar) width /= s->bppcount; @@ -657,6 +658,8 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid bytestream2_init(&s->gb, src, size); bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -679,6 +682,25 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid for (i = 0; i < width; i++) dst[i] = ff_reverse[src[i]]; } + +/* Color processing for DNG images with uncompressed strips (non-tiled) */ +if (is_dng) { +int is_u16, pixel_size_bytes, pixel_size_bits; + +is_u16 = (s->bpp > 8); +pixel_size_bits = (is_u16 ? 16 : 8); +pixel_size_bytes = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + +dng_blit(s, + dst, + 0, // no stride, only 1 line + dst, + 0, // no stride, only 1 line + width / pixel_size_bytes * pixel_size_bits / s->bpp, // need to account for [1, 16] bpp + 1, + is_u16); +} + src += width; break; case TIFF_PACKBITS: @@ -1947,7 +1969,8 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16) { +if (s->is_bayer && s->white_level && s->bpp == 16 && +!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 06/14] lavc/tiff: Fix edge case with full-length/width tiles
From: Nick Renieris In an image [1], the height was equal to the tile length (full-height tile) and after `height % tile_length` was applied to them with the current code, it resulted in the operating tile_length to be 0. This commit makes this leftover logic only applies if it's necessary. Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 4620508d53..37fda15162 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -887,10 +887,14 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int tile_byte_count_offset, tile_byte_count; int tile_count_x, tile_count_y; int tile_width, tile_length; +int has_width_leftover, has_height_leftover; int tile_x = 0, tile_y = 0; int pos_x = 0, pos_y = 0; int ret; +has_width_leftover = (s->width % s->tile_width != 0); +has_height_leftover = (s->height % s->tile_length != 0); + /* Calculate tile counts (round up) */ tile_count_x = (s->width + s->tile_width - 1) / s->tile_width; tile_count_y = (s->height + s->tile_length - 1) / s->tile_length; @@ -900,12 +904,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) tile_x = tile_idx % tile_count_x; tile_y = tile_idx / tile_count_x; -if (tile_x == tile_count_x - 1) // If on the right edge +if (has_width_leftover && tile_x == tile_count_x - 1) // If on the right-most tile tile_width = s->width % s->tile_width; else tile_width = s->tile_width; -if (tile_y == tile_count_y - 1) // If on the bottom edge +if (has_height_leftover && tile_y == tile_count_y - 1) // If on the bottom-most tile tile_length = s->height % s->tile_length; else tile_length = s->tile_length; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 10/14] lavc/tiff: Support decoding of DNGs with single-component JPEGs
From: Nick Renieris 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 --- libavcodec/tiff.c | 61 +++ 1 file changed, 51 insertions(+), 10 deletions(-) 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(AVCod
[FFmpeg-devel] [PATCH v13 07/14] lavc/tiff: Don't apply strips-related logic to tiled images
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 42 ++ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 37fda15162..174ca168c6 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1780,7 +1780,7 @@ again: } } -if (!s->strippos && !s->stripoff) { +if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } @@ -1788,27 +1788,29 @@ again: if ((ret = init_image(s, &frame)) < 0) return ret; -if (s->strips == 1 && !s->stripsize) { -av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); -s->stripsize = avpkt->size - s->stripoff; -} +if (!s->is_tiled) { +if (s->strips == 1 && !s->stripsize) { +av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); +s->stripsize = avpkt->size - s->stripoff; +} -if (s->stripsizesoff) { -if (s->stripsizesoff >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, - avpkt->size - s->stripsizesoff); -} -if (s->strippos) { -if (s->strippos >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripdata, avpkt->data + s->strippos, - avpkt->size - s->strippos); -} +if (s->stripsizesoff) { +if (s->stripsizesoff >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, +avpkt->size - s->stripsizesoff); +} +if (s->strippos) { +if (s->strippos >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripdata, avpkt->data + s->strippos, +avpkt->size - s->strippos); +} -if (s->rps <= 0 || s->rps % s->subsampling[1]) { -av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); -return AVERROR_INVALIDDATA; +if (s->rps <= 0 || s->rps % s->subsampling[1]) { +av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); +return AVERROR_INVALIDDATA; +} } /* Handle DNG images with JPEG-compressed tiles */ -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 09/14] lavc/mjpegdec: Enable decoding of single-component bayer images
From: Nick Renieris Also, ensure no false positives when determining DNG bayer images, by setting them in tiff.c instead of relying on a heuristic. There's no way to determine this just from the JPEG data, so we have to pass this information from outside the MJPEG decoder. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 32 +--- libavcodec/tiff.c | 7 +++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 6391107f78..0a920a7144 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,13 +412,17 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } -/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 - interleaved components and the width stored in their SOF3 markers is the - width of each one. We only output a single component, therefore we need - to adjust the output image width. */ -if (s->lossless == 1 && nb_components == 2) { -s->bayer = 1; -width *= 2; +if (s->bayer) { +if (nb_components == 2) { +/* Bayer images embedded in DNGs can contain 2 interleaved components and the + width stored in their SOF3 markers is the width of each one. We only output + a single component, therefore we need to adjust the output image width. We + handle the deinterleaving (but not the debayering) in this file. */ +width *= 2; +} +/* They can also contain 1 component, which is double the width and half the height +of the final image (rows are interleaved). We don't handle the decoding in this +file, but leave that to the TIFF/DNG decoder. */ } /* if different size, realloc/alloc picture */ @@ -1184,10 +1188,16 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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->bayer && nb_components == 2) { -for (mb_x = 0; mb_x < width; mb_x++) { -((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; -((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} else if (s->bayer) { +if (nb_components == 1) { +/* Leave decoding to the TIFF/DNG decoder (see comment in ff_mjpeg_decode_sof) */ +for (mb_x = 0; mb_x < width; mb_x++) +((uint16_t*)ptr)[mb_x] = buffer[mb_x][0]; +} else if (nb_components == 2) { +for (mb_x = 0; mb_x < width; mb_x++) { +((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; +((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} } } else { for(i=0; igb.buffer; 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, &jpkt); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 08/14] lavc/tiff: Force DNG pixel data endianness on an edge case
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 12 1 file changed, 12 insertions(+) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 174ca168c6..9d20763186 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1038,6 +1038,18 @@ static int init_image(TiffContext *s, ThreadFrame *frame) AV_RL32(s->pattern)); return AVERROR_PATCHWELCOME; } +/* Force endianness as mentioned in 'DNG Specification: Chapter 3: BitsPerSample' +NOTE: The spec actually specifies big-endian, not sure why we need little-endian, + but such images don't work otherwise. */ +if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) +&& (s->bpp != 8 && s->bpp != 16 && s->bpp != 32)) { +switch (s->avctx->pix_fmt) { +case AV_PIX_FMT_BAYER_RGGB16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE; break; +case AV_PIX_FMT_BAYER_BGGR16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16LE; break; +case AV_PIX_FMT_BAYER_GBRG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE; break; +case AV_PIX_FMT_BAYER_GRBG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16LE; break; +} +} break; case 10161: switch (AV_RL32(s->pattern)) { -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 13/14] lavc/tiff: Support DNGs with striped (non-tiled) JPEGs images
From: Nick Renieris DNG samples here can now be decoded: - https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 73 +++ 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 0d931641c2..b9aa4efd02 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -550,6 +550,8 @@ 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 tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -665,6 +667,17 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +/* Decode JPEG-encoded DNGs with strips */ +if (s->compr == TIFF_NEWJPEG && is_dng) { +if (s->strips > 1) { +av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); +return AVERROR_PATCHWELCOME; +} +if ((ret = dng_decode_strip(s->avctx, p)) < 0) +return ret; +return 0; +} + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -859,8 +872,8 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } } -static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, -int tile_byte_count, int x, int y, int w, int h) +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; AVPacket jpkt; @@ -912,7 +925,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return AVERROR_PATCHWELCOME; } -dst_offset = x + frame->linesize[0] * y / pixel_size; +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]; @@ -931,7 +944,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) +static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { TiffContext *s = avctx->priv_data; int tile_idx; @@ -944,6 +957,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int pos_x = 0, pos_y = 0; int ret; +s->jpgframe->width = s->tile_width; +s->jpgframe->height = s->tile_length; + +s->avctx_mjpeg->width = s->tile_width; +s->avctx_mjpeg->height = s->tile_length; + has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); @@ -980,7 +999,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) bytestream2_seek(&s->gb, tile_offset, SEEK_SET); /* Decode JPEG tile and copy it in the reference frame */ -ret = dng_decode_jpeg_tile(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); +ret = dng_decode_jpeg(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); if (ret < 0) return ret; @@ -993,30 +1012,24 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) } } -return 0; -} +/* Frame is ready to be output */ +frame->pict_type = AV_PICTURE_TYPE_I; +frame->key_frame = 1; -static int dng_decode(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { -int ret; +return avpkt->size; +} +static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) +{ TiffContext *s = avctx->priv_data; -s->jpgframe->width = s->tile_width; -s->jpgframe->height = s->tile_length; - -s->avctx_mjpeg->width = s->tile_width; -s->avctx_mjpeg->height = s->tile_length; - -/* Decode all tiles in a frame */ -ret = dng_decode_tiles(avctx, frame); -if (ret < 0) -return ret; +s->jpgframe->width = s->width; +s->jpgframe->height = s->height; -/* Frame is ready to be output */ -frame->pict_type = AV_PICTURE_TYPE_I; -frame->key_frame = 1; +s->avctx_mjpeg->width = s->width; +s->avctx_mjpeg->height = s->height; -return avpkt->size; +return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); } static int ini
[FFmpeg-devel] [PATCH v13 12/14] lavc/mjpegdec: Skip unknown APPx marker on bayer images
From: Nick Renieris Samples: - Embedded JPEG images in the DNG images here: https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 0a920a7144..1f2fabe2df 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1807,8 +1807,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) int len, id, i; len = get_bits(&s->gb, 16); -if (len < 6) -return AVERROR_INVALIDDATA; +if (len < 6) { +if (s->bayer) { +// Pentax K-1 (digital camera) JPEG images embedded in DNG images contain unknown APP0 markers +av_log(s->avctx, AV_LOG_WARNING, "skipping APPx (len=%"PRId32") for bayer-encoded image\n", len); +skip_bits(&s->gb, len); +return 0; +} else +return AVERROR_INVALIDDATA; +} if (8 * len > get_bits_left(&s->gb)) return AVERROR_INVALIDDATA; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 11/14] lavc/tiff: Decode 14-bit DNG images
From: Nick Renieris Sample file: https://drive.google.com/open?id=0B4JyRT3Lth5HVndyOTVOdWktM3J4TFEydTk1MnY3RWlpSzVB Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index ecd87c0b2f..0d931641c2 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -309,14 +309,18 @@ static void av_always_inline horizontal_fill(TiffContext *s, dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; } break; -case 12: { - uint16_t *dst16 = (uint16_t *)dst; - GetBitContext gb; - init_get_bits8(&gb, src, width); - for (int i = 0; i < s->width; i++) { - dst16[i] = get_bits(&gb, 12) << 4; - } - } +case 12: +case 14: { +uint16_t *dst16 = (uint16_t *)dst; +int is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +uint8_t shift = is_dng ? 0 : 16 - bpp; +GetBitContext gb; + +init_get_bits8(&gb, src, width); +for (int i = 0; i < s->width; i++) { +dst16[i] = get_bits(&gb, bpp) << shift; +} +} break; default: if (usePtr) { @@ -1068,6 +1072,7 @@ static int init_image(TiffContext *s, ThreadFrame *frame) } break; case 10121: +case 10141: switch (AV_RL32(s->pattern)) { case 0x02010100: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v13 14/14] lavc/tiff: Default-initialize WhiteLevel DNG tag value
From: Nick Renieris Initialized to `(2 ^ BitsPerSample) - 1` as per the DNG Specification. Also make sure that `BlackLevel < WhiteLevel`. This fixes decoding for "X7 CinemaDNG" samples here: - https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 20 +--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index b9aa4efd02..b985f19fe2 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1773,6 +1773,7 @@ static int decode_frame(AVCodecContext *avctx, GetByteContext stripsizes; GetByteContext stripdata; int retry_for_subifd, retry_for_page; +int is_dng; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -1841,6 +1842,10 @@ again: goto again; } +/* At this point we've decided on which (Sub)IFD to process */ + +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (i = 0; igeotag_count; i++) { const char *keyname = get_geokey_name(s->geotags[i].key); if (!keyname) { @@ -1858,10 +1863,20 @@ again: } } +if (s->white_level == 0) +s->white_level = (1 << s->bpp) - 1; /* Default value as per the spec */ + +if (s->white_level <= s->black_level) { +av_log(avctx, AV_LOG_ERROR, "BlackLevel (%"PRId32") must be less than WhiteLevel (%"PRId32")\n", + s->black_level, s->white_level); +return AVERROR_INVALIDDATA; +} + if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } + /* now we have the data and may start decoding */ if ((ret = init_image(s, &frame)) < 0) return ret; @@ -1893,7 +1908,7 @@ again: /* Handle DNG images with JPEG-compressed tiles */ -if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) && s->is_tiled) { +if (is_dng && s->is_tiled) { if (!s->is_jpeg) { avpriv_report_missing_feature(avctx, "DNG uncompressed tiled images"); return AVERROR_PATCHWELCOME; @@ -2051,8 +2066,7 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16 && -!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { +if (s->is_bayer && s->bpp == 16 && !is_dng && (s->white_level != (1 << s->bpp) - 1)) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 01/14] lavc/mjpegdec: Decode Huffman-coded lossless JPEGs embedded in DNGs
From: Nick Renieris Main image data in DNGs is usually comprised of tiles, each of which is a Huffman-encoded lossless JPEG. Tested for ljpeg regressions with: `ffmpeg -f lavfi -i testsrc=d=1 -vcodec ljpeg test.avi` `ffmpeg test.avi out.avi` The modified code in ljpeg_decode_rgb_scan runs without issues. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 52 +-- libavcodec/mjpegdec.h | 1 + 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index a65bc8df15..6391107f78 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,6 +412,14 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } +/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 + interleaved components and the width stored in their SOF3 markers is the + width of each one. We only output a single component, therefore we need + to adjust the output image width. */ +if (s->lossless == 1 && nb_components == 2) { +s->bayer = 1; +width *= 2; +} /* if different size, realloc/alloc picture */ if (width != s->width || height != s->height || bits != s->bits || @@ -488,6 +496,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } switch (pix_fmt_id) { +case 0x: /* for bayer-encoded huffman lossless JPEGs embedded in DNGs */ +s->avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; +break; case 0x1100: if (s->rgb) s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48; @@ -1041,17 +1052,20 @@ static int handle_rstn(MJpegDecodeContext *s, int nb_components) return reset; } +/* Handles 1 to 4 components */ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform) { int i, mb_x, mb_y; +unsigned width; uint16_t (*buffer)[4]; int left[4], top[4], topleft[4]; const int linesize = s->linesize[0]; const int mask = ((1 << s->bits) - 1) << point_transform; int resync_mb_y = 0; int resync_mb_x = 0; +int vpred[6]; -if (s->nb_components != 3 && s->nb_components != 4) +if (s->nb_components <= 0 || s->nb_components > 4) return AVERROR_INVALIDDATA; if (s->v_max != 1 || s->h_max != 1 || !s->lossless) return AVERROR_INVALIDDATA; @@ -1059,8 +1073,15 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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])); +if (s->restart_interval == 0) +s->restart_interval = INT_MAX; + +if (s->bayer) +width = s->mb_width / nb_components; /* Interleaved, width stored is the total so need to divide */ +else +width = s->mb_width; + +av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, width * 4 * sizeof(s->ljpeg_buffer[0][0])); if (!s->ljpeg_buffer) return AVERROR(ENOMEM); @@ -1078,7 +1099,12 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 ((mb_y * s->width) % s->restart_interval == 0) { +for (i = 0; i < 6; i++) +vpred[i] = 1 << (s->bits-1); +} + +for (mb_x = 0; mb_x < width; mb_x++) { int modified_predictor = predictor; if (get_bits_left(&s->gb) < 1) { @@ -1102,12 +1128,19 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 == 0xF) return -1; +if (!s->bayer || mb_x) { +pred = left[i]; +} else { /* This path runs only for the first line in bayer images */ +vpred[i] += dc; +pred = vpred[i] - dc; +} + +PREDICT(pred, topleft[i], top[i], pred, modified_predictor); + left[i] = buffer[mb_x][i] = mask & (pred + (unsigned)(dc * (1 << point_transform))); } @@ -1151,6 +1184,11 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p ptr[
[FFmpeg-devel] [PATCH v14 02/14] lavc/tiff: Decode embedded JPEGs in DNG images
From: Nick Renieris Used a technique similar to lavc/tdsc.c for invoking the MJPEG decoder. This commit adds support for: - DNG tiles - DNG tile huffman lossless JPEG decoding - DNG 8-bpp ("packed" as dcraw calls it) decoding - DNG color scaling [1] - LinearizationTable tag - BlackLevel tag [1]: As specified in the DNG Specification - Chapter 5 Signed-off-by: Nick Renieris --- configure | 1 + libavcodec/Makefile | 2 +- libavcodec/tiff.c | 313 +++- libavcodec/tiff.h | 2 + 4 files changed, 310 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 34c2adb4a4..112b84f0ba 100755 --- a/configure +++ b/configure @@ -2817,6 +2817,7 @@ tdsc_decoder_deps="zlib" tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" +tiff_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib lzma" tiff_encoder_suggest="zlib" truehd_decoder_select="mlp_parser" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3cd73fbcc6..f814c69996 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -616,7 +616,7 @@ OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o OBJS-$(CONFIG_TDSC_DECODER)+= tdsc.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o -OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o +OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o mjpegdec.o OBJS-$(CONFIG_TIFF_ENCODER)+= tiffenc.o rle.o lzwenc.o tiff_data.o OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index c520d7df83..4c6b835afe 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -35,6 +35,7 @@ #include "libavutil/attributes.h" #include "libavutil/avstring.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +47,7 @@ #include "mathops.h" #include "tiff.h" #include "tiff_data.h" +#include "mjpegdec.h" #include "thread.h" #include "get_bits.h" @@ -54,6 +56,10 @@ typedef struct TiffContext { AVCodecContext *avctx; GetByteContext gb; +/* JPEG decoding for DNG */ +AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG +AVFrame *jpgframe; // decoded JPEG tile + int get_subimage; uint16_t get_page; int get_thumbnail; @@ -76,7 +82,9 @@ typedef struct TiffContext { int is_bayer; uint8_t pattern[4]; +unsigned black_level; unsigned white_level; +const uint16_t *dng_lut; // Pointer to DNG linearization table uint32_t sub_ifd; uint16_t cur_page; @@ -86,6 +94,14 @@ typedef struct TiffContext { int stripsizesoff, stripsize, stripoff, strippos; LZWState *lzw; +/* Tile support */ +int is_tiled; +int tile_byte_counts_offset, tile_offsets_offset; +int tile_width, tile_length; +int tile_count; + +int is_jpeg; + uint8_t *deinvert_buf; int deinvert_buf_size; uint8_t *yuv_line; @@ -257,6 +273,9 @@ 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); + static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, int usePtr, const uint8_t *src, @@ -712,6 +731,204 @@ 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_raw_to_linear16(uint16_t value, +const uint16_t *lut, +uint16_t black_level, +float scale_factor) { +// Lookup table lookup +if (lut) +value = lut[value]; + +// Black level subtraction +value = av_clip_uint16_c((unsigned)value - black_level); + +// Color scaling +value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); + +return value; +} + +static uint16_t av_always_inline dng_raw_to_linear8(uint16_t value, +const uint16_t *lut, +uint1
[FFmpeg-devel] [PATCH v14 06/14] lavc/tiff: Fix edge case with full-length/width tiles
From: Nick Renieris In an image [1], the height was equal to the tile length (full-height tile) and after `height % tile_length` was applied to them with the current code, it resulted in the operating tile_length to be 0. This commit makes this leftover logic only applies if it's necessary. Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 040e83ba7c..14928ed3d5 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -887,10 +887,14 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int tile_byte_count_offset, tile_byte_count; int tile_count_x, tile_count_y; int tile_width, tile_length; +int has_width_leftover, has_height_leftover; int tile_x = 0, tile_y = 0; int pos_x = 0, pos_y = 0; int ret; +has_width_leftover = (s->width % s->tile_width != 0); +has_height_leftover = (s->height % s->tile_length != 0); + /* Calculate tile counts (round up) */ tile_count_x = (s->width + s->tile_width - 1) / s->tile_width; tile_count_y = (s->height + s->tile_length - 1) / s->tile_length; @@ -900,12 +904,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) tile_x = tile_idx % tile_count_x; tile_y = tile_idx / tile_count_x; -if (tile_x == tile_count_x - 1) // If on the right edge +if (has_width_leftover && tile_x == tile_count_x - 1) // If on the right-most tile tile_width = s->width % s->tile_width; else tile_width = s->tile_width; -if (tile_y == tile_count_y - 1) // If on the bottom edge +if (has_height_leftover && tile_y == tile_count_y - 1) // If on the bottom-most tile tile_length = s->height % s->tile_length; else tile_length = s->tile_length; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 04/14] lavc/tiff: Apply color scaling to uncompressed DNGs
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index a2102f32b5..040e83ba7c 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -556,6 +556,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; +int is_dng; if (s->planar) width /= s->bppcount; @@ -657,6 +658,8 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid bytestream2_init(&s->gb, src, size); bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -679,6 +682,25 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid for (i = 0; i < width; i++) dst[i] = ff_reverse[src[i]]; } + +/* Color processing for DNG images with uncompressed strips (non-tiled) */ +if (is_dng) { +int is_u16, pixel_size_bytes, pixel_size_bits; + +is_u16 = (s->bpp > 8); +pixel_size_bits = (is_u16 ? 16 : 8); +pixel_size_bytes = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + +dng_blit(s, + dst, + 0, // no stride, only 1 line + dst, + 0, // no stride, only 1 line + width / pixel_size_bytes * pixel_size_bits / s->bpp, // need to account for [1, 16] bpp + 1, + is_u16); +} + src += width; break; case TIFF_PACKBITS: @@ -1945,7 +1967,8 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16) { +if (s->is_bayer && s->white_level && s->bpp == 16 && +!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 07/14] lavc/tiff: Don't apply strips-related logic to tiled images
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 42 ++ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 14928ed3d5..ff9ac30b3f 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1780,7 +1780,7 @@ again: } } -if (!s->strippos && !s->stripoff) { +if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } @@ -1788,27 +1788,29 @@ again: if ((ret = init_image(s, &frame)) < 0) return ret; -if (s->strips == 1 && !s->stripsize) { -av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); -s->stripsize = avpkt->size - s->stripoff; -} +if (!s->is_tiled) { +if (s->strips == 1 && !s->stripsize) { +av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); +s->stripsize = avpkt->size - s->stripoff; +} -if (s->stripsizesoff) { -if (s->stripsizesoff >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, - avpkt->size - s->stripsizesoff); -} -if (s->strippos) { -if (s->strippos >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripdata, avpkt->data + s->strippos, - avpkt->size - s->strippos); -} +if (s->stripsizesoff) { +if (s->stripsizesoff >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, +avpkt->size - s->stripsizesoff); +} +if (s->strippos) { +if (s->strippos >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripdata, avpkt->data + s->strippos, +avpkt->size - s->strippos); +} -if (s->rps <= 0 || s->rps % s->subsampling[1]) { -av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); -return AVERROR_INVALIDDATA; +if (s->rps <= 0 || s->rps % s->subsampling[1]) { +av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); +return AVERROR_INVALIDDATA; +} } /* Handle DNG images with JPEG-compressed tiles */ -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 03/14] lavc/tiff: Convert DNGs to sRGB color space
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 34 +++--- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 4c6b835afe..a2102f32b5 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -731,14 +731,23 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid return 0; } +static float av_always_inline linear_to_srgb(float value) { +if (value <= 0.0031308) +return value * 12.92; +else +return pow(value * 1.055, 1.0 / 2.4) - 0.055; +} + /** - * Map stored raw sensor values into linear reference values. - * See: DNG Specification - Chapter 5 + * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5) + * Then convert to sRGB color space. */ -static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, -const uint16_t *lut, -uint16_t black_level, -float scale_factor) { +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]; @@ -747,16 +756,19 @@ static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, value = av_clip_uint16_c((unsigned)value - black_level); // Color scaling -value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); +value_norm = (float)value * scale_factor; + +// Color space conversion (sRGB) +value = av_clip_uint16_c((uint16_t)(linear_to_srgb(value_norm) * 0x)); return value; } -static uint16_t av_always_inline dng_raw_to_linear8(uint16_t 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_raw_to_linear16(value, lut, black_level, scale_factor) >> 8; +return dng_process_color16(value, lut, black_level, scale_factor) >> 8; } static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, @@ -774,7 +786,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, uint16_t *src_u16 = (uint16_t *)src; for (col = 0; col < width; col++) -*dst_u16++ = dng_raw_to_linear16(*src_u16++, s->dng_lut, s->black_level, scale_factor); +*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); @@ -782,7 +794,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } else { for (line = 0; line < height; line++) { for (col = 0; col < width; col++) -*dst++ = dng_raw_to_linear8(*src++, s->dng_lut, s->black_level, scale_factor); +*dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); dst += dst_stride; src += src_stride; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 09/14] lavc/mjpegdec: Enable decoding of single-component bayer images
From: Nick Renieris Also, ensure no false positives when determining DNG bayer images, by setting them in tiff.c instead of relying on a heuristic. There's no way to determine this just from the JPEG data, so we have to pass this information from outside the MJPEG decoder. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 32 +--- libavcodec/tiff.c | 7 +++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 6391107f78..0a920a7144 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,13 +412,17 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } -/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 - interleaved components and the width stored in their SOF3 markers is the - width of each one. We only output a single component, therefore we need - to adjust the output image width. */ -if (s->lossless == 1 && nb_components == 2) { -s->bayer = 1; -width *= 2; +if (s->bayer) { +if (nb_components == 2) { +/* Bayer images embedded in DNGs can contain 2 interleaved components and the + width stored in their SOF3 markers is the width of each one. We only output + a single component, therefore we need to adjust the output image width. We + handle the deinterleaving (but not the debayering) in this file. */ +width *= 2; +} +/* They can also contain 1 component, which is double the width and half the height +of the final image (rows are interleaved). We don't handle the decoding in this +file, but leave that to the TIFF/DNG decoder. */ } /* if different size, realloc/alloc picture */ @@ -1184,10 +1188,16 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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->bayer && nb_components == 2) { -for (mb_x = 0; mb_x < width; mb_x++) { -((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; -((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} else if (s->bayer) { +if (nb_components == 1) { +/* Leave decoding to the TIFF/DNG decoder (see comment in ff_mjpeg_decode_sof) */ +for (mb_x = 0; mb_x < width; mb_x++) +((uint16_t*)ptr)[mb_x] = buffer[mb_x][0]; +} else if (nb_components == 2) { +for (mb_x = 0; mb_x < width; mb_x++) { +((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; +((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} } } else { for(i=0; igb.buffer; 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, &jpkt); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 11/14] lavc/tiff: Decode 14-bit DNG images
From: Nick Renieris Sample file: https://drive.google.com/open?id=0B4JyRT3Lth5HVndyOTVOdWktM3J4TFEydTk1MnY3RWlpSzVB Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 36ede2e2ef..62cfd8d99d 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -309,14 +309,18 @@ static void av_always_inline horizontal_fill(TiffContext *s, dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; } break; -case 12: { - uint16_t *dst16 = (uint16_t *)dst; - GetBitContext gb; - init_get_bits8(&gb, src, width); - for (int i = 0; i < s->width; i++) { - dst16[i] = get_bits(&gb, 12) << 4; - } - } +case 12: +case 14: { +uint16_t *dst16 = (uint16_t *)dst; +int is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +uint8_t shift = is_dng ? 0 : 16 - bpp; +GetBitContext gb; + +init_get_bits8(&gb, src, width); +for (int i = 0; i < s->width; i++) { +dst16[i] = get_bits(&gb, bpp) << shift; +} +} break; default: if (usePtr) { @@ -1068,6 +1072,7 @@ static int init_image(TiffContext *s, ThreadFrame *frame) } break; case 10121: +case 10141: switch (AV_RL32(s->pattern)) { case 0x02010100: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 10/14] lavc/tiff: Support decoding of DNGs with single-component JPEGs
From: Nick Renieris 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 --- libavcodec/tiff.c | 61 +++ 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 39857a64bc..36ede2e2ef 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(AVCod
[FFmpeg-devel] [PATCH v14 08/14] lavc/tiff: Force DNG pixel data endianness on an edge case
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 12 1 file changed, 12 insertions(+) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index ff9ac30b3f..709bbfb301 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1038,6 +1038,18 @@ static int init_image(TiffContext *s, ThreadFrame *frame) AV_RL32(s->pattern)); return AVERROR_PATCHWELCOME; } +/* Force endianness as mentioned in 'DNG Specification: Chapter 3: BitsPerSample' +NOTE: The spec actually specifies big-endian, not sure why we need little-endian, + but such images don't work otherwise. */ +if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) +&& (s->bpp != 8 && s->bpp != 16 && s->bpp != 32)) { +switch (s->avctx->pix_fmt) { +case AV_PIX_FMT_BAYER_RGGB16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE; break; +case AV_PIX_FMT_BAYER_BGGR16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16LE; break; +case AV_PIX_FMT_BAYER_GBRG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE; break; +case AV_PIX_FMT_BAYER_GRBG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16LE; break; +} +} break; case 10161: switch (AV_RL32(s->pattern)) { -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 12/14] lavc/mjpegdec: Skip unknown APPx marker on bayer images
From: Nick Renieris Samples: - Embedded JPEG images in the DNG images here: https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 0a920a7144..1f2fabe2df 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1807,8 +1807,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) int len, id, i; len = get_bits(&s->gb, 16); -if (len < 6) -return AVERROR_INVALIDDATA; +if (len < 6) { +if (s->bayer) { +// Pentax K-1 (digital camera) JPEG images embedded in DNG images contain unknown APP0 markers +av_log(s->avctx, AV_LOG_WARNING, "skipping APPx (len=%"PRId32") for bayer-encoded image\n", len); +skip_bits(&s->gb, len); +return 0; +} else +return AVERROR_INVALIDDATA; +} if (8 * len > get_bits_left(&s->gb)) return AVERROR_INVALIDDATA; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 05/14] lavc/jpegtables: Handle multiple mappings to the same value
From: Nick Renieris Some JPEGs [1] have incorrect DHT entries that map 2 codes to the same value. The second (last) mapping does not ever actually appear in the code stream, therefore ignoring any mappings after the first one fixes this. Without this, an "mjpeg_decode_dc: bad vlc: 0:0" error is thrown. In all known files, the 2 codes are mapped to symbol 0 so only that case is checked. --- [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/jpegtables.c | 17 ++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index cbe5523cb4..fa5c6f9fc5 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -130,14 +130,25 @@ void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, { int i, j, k,nb, code, sym; -code = 0; +/* Some badly encoded files [1] map 2 different codes to symbol 0. + Only the first one is valid, so we zero-initialize this here and + make sure we only set it once (the first time) in the loop below. + + [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: +https://www.dji.com/gr/zenmuse-x7/info#downloads + */ +huff_size[0] = 0; + k = 0; +code = 0; for(i=1;i<=16;i++) { nb = bits_table[i]; for(j=0;jhttps://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 14/14] lavc/tiff: Default-initialize WhiteLevel DNG tag value
From: Nick Renieris Initialized to `(2 ^ BitsPerSample) - 1` as per the DNG Specification. Also make sure that `BlackLevel < WhiteLevel`. This fixes decoding for "X7 CinemaDNG" samples here: - https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 22 +++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index b9aa4efd02..9cf593e092 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1773,6 +1773,7 @@ static int decode_frame(AVCodecContext *avctx, GetByteContext stripsizes; GetByteContext stripdata; int retry_for_subifd, retry_for_page; +int is_dng; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -1841,6 +1842,10 @@ again: goto again; } +/* At this point we've decided on which (Sub)IFD to process */ + +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (i = 0; igeotag_count; i++) { const char *keyname = get_geokey_name(s->geotags[i].key); if (!keyname) { @@ -1858,10 +1863,22 @@ again: } } +if (is_dng) { +if (s->white_level == 0) +s->white_level = (1 << s->bpp) - 1; /* Default value as per the spec */ + +if (s->white_level <= s->black_level) { +av_log(avctx, AV_LOG_ERROR, "BlackLevel (%"PRId32") must be less than WhiteLevel (%"PRId32")\n", +s->black_level, s->white_level); +return AVERROR_INVALIDDATA; +} +} + if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } + /* now we have the data and may start decoding */ if ((ret = init_image(s, &frame)) < 0) return ret; @@ -1893,7 +1910,7 @@ again: /* Handle DNG images with JPEG-compressed tiles */ -if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) && s->is_tiled) { +if (is_dng && s->is_tiled) { if (!s->is_jpeg) { avpriv_report_missing_feature(avctx, "DNG uncompressed tiled images"); return AVERROR_PATCHWELCOME; @@ -2051,8 +2068,7 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16 && -!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { +if (s->is_bayer && s->white_level && s->bpp == 16 && !is_dng) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v14 13/14] lavc/tiff: Support DNGs with striped (non-tiled) JPEGs images
From: Nick Renieris DNG samples here can now be decoded: - https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 61 --- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 62cfd8d99d..b9aa4efd02 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -550,6 +550,8 @@ 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 tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -665,6 +667,17 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +/* Decode JPEG-encoded DNGs with strips */ +if (s->compr == TIFF_NEWJPEG && is_dng) { +if (s->strips > 1) { +av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); +return AVERROR_PATCHWELCOME; +} +if ((ret = dng_decode_strip(s->avctx, p)) < 0) +return ret; +return 0; +} + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -859,8 +872,8 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } } -static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, -int tile_byte_count, int x, int y, int w, int h) +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; AVPacket jpkt; @@ -912,7 +925,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return AVERROR_PATCHWELCOME; } -dst_offset = x + frame->linesize[0] * y / pixel_size; +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]; @@ -931,7 +944,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) +static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { TiffContext *s = avctx->priv_data; int tile_idx; @@ -944,6 +957,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int pos_x = 0, pos_y = 0; int ret; +s->jpgframe->width = s->tile_width; +s->jpgframe->height = s->tile_length; + +s->avctx_mjpeg->width = s->tile_width; +s->avctx_mjpeg->height = s->tile_length; + has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); @@ -980,7 +999,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) bytestream2_seek(&s->gb, tile_offset, SEEK_SET); /* Decode JPEG tile and copy it in the reference frame */ -ret = dng_decode_jpeg_tile(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); +ret = dng_decode_jpeg(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); if (ret < 0) return ret; @@ -993,30 +1012,24 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) } } -return 0; -} +/* Frame is ready to be output */ +frame->pict_type = AV_PICTURE_TYPE_I; +frame->key_frame = 1; -static int dng_decode(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { -int ret; +return avpkt->size; +} +static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) +{ TiffContext *s = avctx->priv_data; -s->jpgframe->width = s->tile_width; -s->jpgframe->height = s->tile_length; - -s->avctx_mjpeg->width = s->tile_width; -s->avctx_mjpeg->height = s->tile_length; - -/* Decode all tiles in a frame */ -ret = dng_decode_tiles(avctx, frame); -if (ret < 0) -return ret; +s->jpgframe->width = s->width; +s->jpgframe->height = s->height; -/* Frame is ready to be output */ -frame->pict_type = AV_PICTURE_TYPE_I; -frame->key_frame = 1; +s->avctx_mjpeg->width = s->width; +s->avctx_mjpeg->height = s->height; -return avpkt->size; +return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); } stat
[FFmpeg-devel] [PATCH v15 06/15] lavc/tiff: Fix edge case with full-length/width tiles
In an image [1], the height was equal to the tile length (full-height tile) and after `height % tile_length` was applied to them with the current code, it resulted in the operating tile_length to be 0. This commit makes this leftover logic only applies if it's necessary. Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index dd1295fad6..257230c386 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -887,10 +887,14 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int tile_byte_count_offset, tile_byte_count; int tile_count_x, tile_count_y; int tile_width, tile_length; +int has_width_leftover, has_height_leftover; int tile_x = 0, tile_y = 0; int pos_x = 0, pos_y = 0; int ret; +has_width_leftover = (s->width % s->tile_width != 0); +has_height_leftover = (s->height % s->tile_length != 0); + /* Calculate tile counts (round up) */ tile_count_x = (s->width + s->tile_width - 1) / s->tile_width; tile_count_y = (s->height + s->tile_length - 1) / s->tile_length; @@ -900,12 +904,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) tile_x = tile_idx % tile_count_x; tile_y = tile_idx / tile_count_x; -if (tile_x == tile_count_x - 1) // If on the right edge +if (has_width_leftover && tile_x == tile_count_x - 1) // If on the right-most tile tile_width = s->width % s->tile_width; else tile_width = s->tile_width; -if (tile_y == tile_count_y - 1) // If on the bottom edge +if (has_height_leftover && tile_y == tile_count_y - 1) // If on the bottom-most tile tile_length = s->height % s->tile_length; else tile_length = s->tile_length; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 10/15] lavc/tiff: Support decoding of DNGs with single-component JPEGs
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 --- libavcodec/tiff.c | 61 +++ 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 77acf9f838..35234dc05e 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 * s->bppcount, // 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 *
[FFmpeg-devel] [PATCH v15 11/15] lavc/tiff: Decode 10-bit and 14-bit DNG images
10-bit sample: http://www.rawsamples.ch/raws/phones/RAW_ONEPLUS_ONE-A0001.DNG 14-bit sample: https://drive.google.com/open?id=0B4JyRT3Lth5HVndyOTVOdWktM3J4TFEydTk1MnY3RWlpSzVB Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 23 +++ 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 35234dc05e..d5efd05d7c 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -309,14 +309,19 @@ static void av_always_inline horizontal_fill(TiffContext *s, dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; } break; -case 12: { - uint16_t *dst16 = (uint16_t *)dst; - GetBitContext gb; - init_get_bits8(&gb, src, width); - for (int i = 0; i < s->width; i++) { - dst16[i] = get_bits(&gb, 12) << 4; - } - } +case 10: +case 12: +case 14: { +uint16_t *dst16 = (uint16_t *)dst; +int is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +uint8_t shift = is_dng ? 0 : 16 - bpp; +GetBitContext gb; + +init_get_bits8(&gb, src, width); +for (int i = 0; i < s->width; i++) { +dst16[i] = get_bits(&gb, bpp) << shift; +} +} break; default: if (usePtr) { @@ -1067,7 +1072,9 @@ static int init_image(TiffContext *s, ThreadFrame *frame) return AVERROR_PATCHWELCOME; } break; +case 10101: case 10121: +case 10141: switch (AV_RL32(s->pattern)) { case 0x02010100: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 12/15] lavc/mjpegdec: Skip unknown APPx marker on bayer images
Samples: - Embedded JPEG images in the DNG images here: https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 0a920a7144..1f2fabe2df 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1807,8 +1807,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) int len, id, i; len = get_bits(&s->gb, 16); -if (len < 6) -return AVERROR_INVALIDDATA; +if (len < 6) { +if (s->bayer) { +// Pentax K-1 (digital camera) JPEG images embedded in DNG images contain unknown APP0 markers +av_log(s->avctx, AV_LOG_WARNING, "skipping APPx (len=%"PRId32") for bayer-encoded image\n", len); +skip_bits(&s->gb, len); +return 0; +} else +return AVERROR_INVALIDDATA; +} if (8 * len > get_bits_left(&s->gb)) return AVERROR_INVALIDDATA; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 14/15] lavc/tiff: Default-initialize WhiteLevel DNG tag value
Initialized to `(2 ^ BitsPerSample) - 1` as per the DNG Specification. Also make sure that `BlackLevel < WhiteLevel`. This fixes decoding for "X7 CinemaDNG" samples here: - https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 22 +++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index df2554be86..377662c897 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1775,6 +1775,7 @@ static int decode_frame(AVCodecContext *avctx, GetByteContext stripsizes; GetByteContext stripdata; int retry_for_subifd, retry_for_page; +int is_dng; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -1843,6 +1844,10 @@ again: goto again; } +/* At this point we've decided on which (Sub)IFD to process */ + +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (i = 0; igeotag_count; i++) { const char *keyname = get_geokey_name(s->geotags[i].key); if (!keyname) { @@ -1860,10 +1865,22 @@ again: } } +if (is_dng) { +if (s->white_level == 0) +s->white_level = (1 << s->bpp) - 1; /* Default value as per the spec */ + +if (s->white_level <= s->black_level) { +av_log(avctx, AV_LOG_ERROR, "BlackLevel (%"PRId32") must be less than WhiteLevel (%"PRId32")\n", +s->black_level, s->white_level); +return AVERROR_INVALIDDATA; +} +} + if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } + /* now we have the data and may start decoding */ if ((ret = init_image(s, &frame)) < 0) return ret; @@ -1895,7 +1912,7 @@ again: /* Handle DNG images with JPEG-compressed tiles */ -if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) && s->is_tiled) { +if (is_dng && s->is_tiled) { if (!s->is_jpeg) { avpriv_report_missing_feature(avctx, "DNG uncompressed tiled images"); return AVERROR_PATCHWELCOME; @@ -2053,8 +2070,7 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16 && -!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { +if (s->is_bayer && s->white_level && s->bpp == 16 && !is_dng) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 08/15] lavc/tiff: Force DNG pixel data endianness on an edge case
Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 12 1 file changed, 12 insertions(+) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 1ca9a59dbf..d9750891d4 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1038,6 +1038,18 @@ static int init_image(TiffContext *s, ThreadFrame *frame) AV_RL32(s->pattern)); return AVERROR_PATCHWELCOME; } +/* Force endianness as mentioned in 'DNG Specification: Chapter 3: BitsPerSample' +NOTE: The spec actually specifies big-endian, not sure why we need little-endian, + but such images don't work otherwise. */ +if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) +&& (s->bpp != 8 && s->bpp != 16 && s->bpp != 32)) { +switch (s->avctx->pix_fmt) { +case AV_PIX_FMT_BAYER_RGGB16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE; break; +case AV_PIX_FMT_BAYER_BGGR16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16LE; break; +case AV_PIX_FMT_BAYER_GBRG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE; break; +case AV_PIX_FMT_BAYER_GRBG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16LE; break; +} +} break; case 10161: switch (AV_RL32(s->pattern)) { -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 15/15] lavc/tiff: Enable decoding of LinearRaw images
"LinearRaw" is a value that the PhotometricInterpretation tag can be set to on DNG images that contain color information for all channels instead of being bayer-encoded ("CFA" value). The DNG decoder is complete enough that we can enable this now. Sample: - http://www.rawsamples.ch/raws/nikon/SCANNER_NIKON_LS5000.DNG Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 377662c897..3166a3e5c8 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1495,6 +1495,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_PHOTOMETRIC_SEPARATED: case TIFF_PHOTOMETRIC_YCBCR: case TIFF_PHOTOMETRIC_CFA: +case TIFF_PHOTOMETRIC_LINEAR_RAW: // Used by DNG images s->photometric = value; break; case TIFF_PHOTOMETRIC_ALPHA_MASK: @@ -1503,7 +1504,6 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_PHOTOMETRIC_ITU_LAB: case TIFF_PHOTOMETRIC_LOG_L: case TIFF_PHOTOMETRIC_LOG_LUV: -case TIFF_PHOTOMETRIC_LINEAR_RAW: avpriv_report_missing_feature(s->avctx, "PhotometricInterpretation 0x%04X", value); -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 04/15] lavc/tiff: Apply color scaling to uncompressed DNGs
Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index a2102f32b5..dd1295fad6 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -556,6 +556,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; +int is_dng; if (s->planar) width /= s->bppcount; @@ -657,6 +658,8 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid bytestream2_init(&s->gb, src, size); bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -679,6 +682,25 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid for (i = 0; i < width; i++) dst[i] = ff_reverse[src[i]]; } + +/* Color processing for DNG images with uncompressed strips (non-tiled) */ +if (is_dng) { +int is_u16, pixel_size_bytes, pixel_size_bits; + +is_u16 = (s->bpp > 8); +pixel_size_bits = (is_u16 ? 16 : 8); +pixel_size_bytes = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + +dng_blit(s, + dst, + 0, // no stride, only 1 line + dst, + 0, // no stride, only 1 line + width / pixel_size_bytes * pixel_size_bits / s->bpp * s->bppcount, // need to account for [1, 16] bpp + 1, + is_u16); +} + src += width; break; case TIFF_PACKBITS: @@ -1945,7 +1967,8 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16) { +if (s->is_bayer && s->white_level && s->bpp == 16 && +!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 09/15] lavc/mjpegdec: Enable decoding of single-component bayer images
Also, ensure no false positives when determining DNG bayer images, by setting them in tiff.c instead of relying on a heuristic. There's no way to determine this just from the JPEG data, so we have to pass this information from outside the MJPEG decoder. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 32 +--- libavcodec/tiff.c | 7 +++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 6391107f78..0a920a7144 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,13 +412,17 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } -/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 - interleaved components and the width stored in their SOF3 markers is the - width of each one. We only output a single component, therefore we need - to adjust the output image width. */ -if (s->lossless == 1 && nb_components == 2) { -s->bayer = 1; -width *= 2; +if (s->bayer) { +if (nb_components == 2) { +/* Bayer images embedded in DNGs can contain 2 interleaved components and the + width stored in their SOF3 markers is the width of each one. We only output + a single component, therefore we need to adjust the output image width. We + handle the deinterleaving (but not the debayering) in this file. */ +width *= 2; +} +/* They can also contain 1 component, which is double the width and half the height +of the final image (rows are interleaved). We don't handle the decoding in this +file, but leave that to the TIFF/DNG decoder. */ } /* if different size, realloc/alloc picture */ @@ -1184,10 +1188,16 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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->bayer && nb_components == 2) { -for (mb_x = 0; mb_x < width; mb_x++) { -((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; -((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} else if (s->bayer) { +if (nb_components == 1) { +/* Leave decoding to the TIFF/DNG decoder (see comment in ff_mjpeg_decode_sof) */ +for (mb_x = 0; mb_x < width; mb_x++) +((uint16_t*)ptr)[mb_x] = buffer[mb_x][0]; +} else if (nb_components == 2) { +for (mb_x = 0; mb_x < width; mb_x++) { +((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; +((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} } } else { for(i=0; igb.buffer; 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, &jpkt); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 02/15] lavc/tiff: Decode embedded JPEGs in DNG images
Used a technique similar to lavc/tdsc.c for invoking the MJPEG decoder. This commit adds support for: - DNG tiles - DNG tile huffman lossless JPEG decoding - DNG 8-bpp ("packed" as dcraw calls it) decoding - DNG color scaling [1] - LinearizationTable tag - BlackLevel tag [1]: As specified in the DNG Specification - Chapter 5 Signed-off-by: Nick Renieris --- configure | 1 + libavcodec/Makefile | 2 +- libavcodec/tiff.c | 313 +++- libavcodec/tiff.h | 2 + 4 files changed, 310 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 34c2adb4a4..112b84f0ba 100755 --- a/configure +++ b/configure @@ -2817,6 +2817,7 @@ tdsc_decoder_deps="zlib" tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" +tiff_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib lzma" tiff_encoder_suggest="zlib" truehd_decoder_select="mlp_parser" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3cd73fbcc6..f814c69996 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -616,7 +616,7 @@ OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o OBJS-$(CONFIG_TDSC_DECODER)+= tdsc.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o -OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o +OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o mjpegdec.o OBJS-$(CONFIG_TIFF_ENCODER)+= tiffenc.o rle.o lzwenc.o tiff_data.o OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index c520d7df83..4c6b835afe 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -35,6 +35,7 @@ #include "libavutil/attributes.h" #include "libavutil/avstring.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +47,7 @@ #include "mathops.h" #include "tiff.h" #include "tiff_data.h" +#include "mjpegdec.h" #include "thread.h" #include "get_bits.h" @@ -54,6 +56,10 @@ typedef struct TiffContext { AVCodecContext *avctx; GetByteContext gb; +/* JPEG decoding for DNG */ +AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG +AVFrame *jpgframe; // decoded JPEG tile + int get_subimage; uint16_t get_page; int get_thumbnail; @@ -76,7 +82,9 @@ typedef struct TiffContext { int is_bayer; uint8_t pattern[4]; +unsigned black_level; unsigned white_level; +const uint16_t *dng_lut; // Pointer to DNG linearization table uint32_t sub_ifd; uint16_t cur_page; @@ -86,6 +94,14 @@ typedef struct TiffContext { int stripsizesoff, stripsize, stripoff, strippos; LZWState *lzw; +/* Tile support */ +int is_tiled; +int tile_byte_counts_offset, tile_offsets_offset; +int tile_width, tile_length; +int tile_count; + +int is_jpeg; + uint8_t *deinvert_buf; int deinvert_buf_size; uint8_t *yuv_line; @@ -257,6 +273,9 @@ 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); + static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, int usePtr, const uint8_t *src, @@ -712,6 +731,204 @@ 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_raw_to_linear16(uint16_t value, +const uint16_t *lut, +uint16_t black_level, +float scale_factor) { +// Lookup table lookup +if (lut) +value = lut[value]; + +// Black level subtraction +value = av_clip_uint16_c((unsigned)value - black_level); + +// Color scaling +value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); + +return value; +} + +static uint16_t av_always_inline dng_raw_to_linear8(uint16_t value, +const uint16_t *lut, +uint16_t black_level, +
[FFmpeg-devel] [PATCH v15 07/15] lavc/tiff: Don't apply strips-related logic to tiled images
Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 42 ++ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 257230c386..1ca9a59dbf 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1780,7 +1780,7 @@ again: } } -if (!s->strippos && !s->stripoff) { +if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } @@ -1788,27 +1788,29 @@ again: if ((ret = init_image(s, &frame)) < 0) return ret; -if (s->strips == 1 && !s->stripsize) { -av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); -s->stripsize = avpkt->size - s->stripoff; -} +if (!s->is_tiled) { +if (s->strips == 1 && !s->stripsize) { +av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); +s->stripsize = avpkt->size - s->stripoff; +} -if (s->stripsizesoff) { -if (s->stripsizesoff >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, - avpkt->size - s->stripsizesoff); -} -if (s->strippos) { -if (s->strippos >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripdata, avpkt->data + s->strippos, - avpkt->size - s->strippos); -} +if (s->stripsizesoff) { +if (s->stripsizesoff >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, +avpkt->size - s->stripsizesoff); +} +if (s->strippos) { +if (s->strippos >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripdata, avpkt->data + s->strippos, +avpkt->size - s->strippos); +} -if (s->rps <= 0 || s->rps % s->subsampling[1]) { -av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); -return AVERROR_INVALIDDATA; +if (s->rps <= 0 || s->rps % s->subsampling[1]) { +av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); +return AVERROR_INVALIDDATA; +} } /* Handle DNG images with JPEG-compressed tiles */ -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 13/15] lavc/tiff: Support DNGs with striped (non-tiled) JPEGs images
DNG samples here can now be decoded: - https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 61 --- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index d5efd05d7c..df2554be86 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -551,6 +551,8 @@ 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 tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -666,6 +668,17 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +/* Decode JPEG-encoded DNGs with strips */ +if (s->compr == TIFF_NEWJPEG && is_dng) { +if (s->strips > 1) { +av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); +return AVERROR_PATCHWELCOME; +} +if ((ret = dng_decode_strip(s->avctx, p)) < 0) +return ret; +return 0; +} + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -860,8 +873,8 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } } -static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, -int tile_byte_count, int x, int y, int w, int h) +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; AVPacket jpkt; @@ -913,7 +926,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return AVERROR_PATCHWELCOME; } -dst_offset = x + frame->linesize[0] * y / pixel_size; +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]; @@ -932,7 +945,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) +static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { TiffContext *s = avctx->priv_data; int tile_idx; @@ -945,6 +958,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int pos_x = 0, pos_y = 0; int ret; +s->jpgframe->width = s->tile_width; +s->jpgframe->height = s->tile_length; + +s->avctx_mjpeg->width = s->tile_width; +s->avctx_mjpeg->height = s->tile_length; + has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); @@ -981,7 +1000,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) bytestream2_seek(&s->gb, tile_offset, SEEK_SET); /* Decode JPEG tile and copy it in the reference frame */ -ret = dng_decode_jpeg_tile(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); +ret = dng_decode_jpeg(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); if (ret < 0) return ret; @@ -994,30 +1013,24 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) } } -return 0; -} +/* Frame is ready to be output */ +frame->pict_type = AV_PICTURE_TYPE_I; +frame->key_frame = 1; -static int dng_decode(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { -int ret; +return avpkt->size; +} +static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) +{ TiffContext *s = avctx->priv_data; -s->jpgframe->width = s->tile_width; -s->jpgframe->height = s->tile_length; - -s->avctx_mjpeg->width = s->tile_width; -s->avctx_mjpeg->height = s->tile_length; - -/* Decode all tiles in a frame */ -ret = dng_decode_tiles(avctx, frame); -if (ret < 0) -return ret; +s->jpgframe->width = s->width; +s->jpgframe->height = s->height; -/* Frame is ready to be output */ -frame->pict_type = AV_PICTURE_TYPE_I; -frame->key_frame = 1; +s->avctx_mjpeg->width = s->width; +s->avctx_mjpeg->height = s->height; -return avpkt->size; +return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); } static int init_image(TiffContext *s, Thr
[FFmpeg-devel] [PATCH v15 03/15] lavc/tiff: Convert DNGs to sRGB color space
Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 34 +++--- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 4c6b835afe..a2102f32b5 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -731,14 +731,23 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid return 0; } +static float av_always_inline linear_to_srgb(float value) { +if (value <= 0.0031308) +return value * 12.92; +else +return pow(value * 1.055, 1.0 / 2.4) - 0.055; +} + /** - * Map stored raw sensor values into linear reference values. - * See: DNG Specification - Chapter 5 + * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5) + * Then convert to sRGB color space. */ -static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, -const uint16_t *lut, -uint16_t black_level, -float scale_factor) { +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]; @@ -747,16 +756,19 @@ static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, value = av_clip_uint16_c((unsigned)value - black_level); // Color scaling -value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); +value_norm = (float)value * scale_factor; + +// Color space conversion (sRGB) +value = av_clip_uint16_c((uint16_t)(linear_to_srgb(value_norm) * 0x)); return value; } -static uint16_t av_always_inline dng_raw_to_linear8(uint16_t 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_raw_to_linear16(value, lut, black_level, scale_factor) >> 8; +return dng_process_color16(value, lut, black_level, scale_factor) >> 8; } static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, @@ -774,7 +786,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, uint16_t *src_u16 = (uint16_t *)src; for (col = 0; col < width; col++) -*dst_u16++ = dng_raw_to_linear16(*src_u16++, s->dng_lut, s->black_level, scale_factor); +*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); @@ -782,7 +794,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } else { for (line = 0; line < height; line++) { for (col = 0; col < width; col++) -*dst++ = dng_raw_to_linear8(*src++, s->dng_lut, s->black_level, scale_factor); +*dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); dst += dst_stride; src += src_stride; -- 2.17.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v15 01/15] lavc/mjpegdec: Decode Huffman-coded lossless JPEGs embedded in DNGs
Main image data in DNGs is usually comprised of tiles, each of which is a Huffman-encoded lossless JPEG. Tested for ljpeg regressions with: `ffmpeg -f lavfi -i testsrc=d=1 -vcodec ljpeg test.avi` `ffmpeg test.avi out.avi` The modified code in ljpeg_decode_rgb_scan runs without issues. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 52 +-- libavcodec/mjpegdec.h | 1 + 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index a65bc8df15..6391107f78 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,6 +412,14 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } +/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 + interleaved components and the width stored in their SOF3 markers is the + width of each one. We only output a single component, therefore we need + to adjust the output image width. */ +if (s->lossless == 1 && nb_components == 2) { +s->bayer = 1; +width *= 2; +} /* if different size, realloc/alloc picture */ if (width != s->width || height != s->height || bits != s->bits || @@ -488,6 +496,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } switch (pix_fmt_id) { +case 0x: /* for bayer-encoded huffman lossless JPEGs embedded in DNGs */ +s->avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; +break; case 0x1100: if (s->rgb) s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48; @@ -1041,17 +1052,20 @@ static int handle_rstn(MJpegDecodeContext *s, int nb_components) return reset; } +/* Handles 1 to 4 components */ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform) { int i, mb_x, mb_y; +unsigned width; uint16_t (*buffer)[4]; int left[4], top[4], topleft[4]; const int linesize = s->linesize[0]; const int mask = ((1 << s->bits) - 1) << point_transform; int resync_mb_y = 0; int resync_mb_x = 0; +int vpred[6]; -if (s->nb_components != 3 && s->nb_components != 4) +if (s->nb_components <= 0 || s->nb_components > 4) return AVERROR_INVALIDDATA; if (s->v_max != 1 || s->h_max != 1 || !s->lossless) return AVERROR_INVALIDDATA; @@ -1059,8 +1073,15 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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])); +if (s->restart_interval == 0) +s->restart_interval = INT_MAX; + +if (s->bayer) +width = s->mb_width / nb_components; /* Interleaved, width stored is the total so need to divide */ +else +width = s->mb_width; + +av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, width * 4 * sizeof(s->ljpeg_buffer[0][0])); if (!s->ljpeg_buffer) return AVERROR(ENOMEM); @@ -1078,7 +1099,12 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 ((mb_y * s->width) % s->restart_interval == 0) { +for (i = 0; i < 6; i++) +vpred[i] = 1 << (s->bits-1); +} + +for (mb_x = 0; mb_x < width; mb_x++) { int modified_predictor = predictor; if (get_bits_left(&s->gb) < 1) { @@ -1102,12 +1128,19 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 == 0xF) return -1; +if (!s->bayer || mb_x) { +pred = left[i]; +} else { /* This path runs only for the first line in bayer images */ +vpred[i] += dc; +pred = vpred[i] - dc; +} + +PREDICT(pred, topleft[i], top[i], pred, modified_predictor); + left[i] = buffer[mb_x][i] = mask & (pred + (unsigned)(dc * (1 << point_transform))); } @@ -1151,6 +1184,11 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p ptr[3*mb_x + 0] = buffer
[FFmpeg-devel] [PATCH v15 05/15] lavc/jpegtables: Handle multiple mappings to the same value
Some JPEGs [1] have incorrect DHT entries that map 2 codes to the same value. The second (last) mapping does not ever actually appear in the code stream, therefore ignoring any mappings after the first one fixes this. Without this, an "mjpeg_decode_dc: bad vlc: 0:0" error is thrown. In all known files, the 2 codes are mapped to symbol 0 so only that case is checked. --- [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/jpegtables.c | 17 ++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index cbe5523cb4..fa5c6f9fc5 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -130,14 +130,25 @@ void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, { int i, j, k,nb, code, sym; -code = 0; +/* Some badly encoded files [1] map 2 different codes to symbol 0. + Only the first one is valid, so we zero-initialize this here and + make sure we only set it once (the first time) in the loop below. + + [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: +https://www.dji.com/gr/zenmuse-x7/info#downloads + */ +huff_size[0] = 0; + k = 0; +code = 0; for(i=1;i<=16;i++) { nb = bits_table[i]; for(j=0;jhttps://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 15/15] lavc/tiff: Enable decoding of LinearRaw images
From: Nick Renieris "LinearRaw" is a value that the PhotometricInterpretation tag can be set to on DNG images that contain color information for all channels instead of being bayer-encoded ("CFA" value). The DNG decoder is complete enough that we can enable this now. Sample: - http://www.rawsamples.ch/raws/nikon/SCANNER_NIKON_LS5000.DNG Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index c927400a40..da8f5b133e 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1495,6 +1495,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_PHOTOMETRIC_SEPARATED: case TIFF_PHOTOMETRIC_YCBCR: case TIFF_PHOTOMETRIC_CFA: +case TIFF_PHOTOMETRIC_LINEAR_RAW: // Used by DNG images s->photometric = value; break; case TIFF_PHOTOMETRIC_ALPHA_MASK: @@ -1503,7 +1504,6 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_PHOTOMETRIC_ITU_LAB: case TIFF_PHOTOMETRIC_LOG_L: case TIFF_PHOTOMETRIC_LOG_LUV: -case TIFF_PHOTOMETRIC_LINEAR_RAW: avpriv_report_missing_feature(s->avctx, "PhotometricInterpretation 0x%04X", value); -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 14/15] lavc/tiff: Default-initialize WhiteLevel DNG tag value
From: Nick Renieris Initialized to `(2 ^ BitsPerSample) - 1` as per the DNG Specification. Also make sure that `BlackLevel < WhiteLevel`. This fixes decoding for "X7 CinemaDNG" samples here: - https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 22 +++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index dfaef1927d..c927400a40 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1775,6 +1775,7 @@ static int decode_frame(AVCodecContext *avctx, GetByteContext stripsizes; GetByteContext stripdata; int retry_for_subifd, retry_for_page; +int is_dng; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -1843,6 +1844,10 @@ again: goto again; } +/* At this point we've decided on which (Sub)IFD to process */ + +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (i = 0; igeotag_count; i++) { const char *keyname = get_geokey_name(s->geotags[i].key); if (!keyname) { @@ -1860,10 +1865,22 @@ again: } } +if (is_dng) { +if (s->white_level == 0) +s->white_level = (1 << s->bpp) - 1; /* Default value as per the spec */ + +if (s->white_level <= s->black_level) { +av_log(avctx, AV_LOG_ERROR, "BlackLevel (%"PRId32") must be less than WhiteLevel (%"PRId32")\n", +s->black_level, s->white_level); +return AVERROR_INVALIDDATA; +} +} + if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } + /* now we have the data and may start decoding */ if ((ret = init_image(s, &frame)) < 0) return ret; @@ -1895,7 +1912,7 @@ again: /* Handle DNG images with JPEG-compressed tiles */ -if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) && s->is_tiled) { +if (is_dng && s->is_tiled) { if (!s->is_jpeg) { avpriv_report_missing_feature(avctx, "DNG uncompressed tiled images"); return AVERROR_PATCHWELCOME; @@ -2053,8 +2070,7 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16 && -!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { +if (s->is_bayer && s->white_level && s->bpp == 16 && !is_dng) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 13/15] lavc/tiff: Support DNGs with striped (non-tiled) JPEGs images
From: Nick Renieris DNG samples here can now be decoded: - https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 61 --- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 61a140fe09..dfaef1927d 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -551,6 +551,8 @@ 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 tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -666,6 +668,17 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +/* Decode JPEG-encoded DNGs with strips */ +if (s->compr == TIFF_NEWJPEG && is_dng) { +if (s->strips > 1) { +av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); +return AVERROR_PATCHWELCOME; +} +if ((ret = dng_decode_strip(s->avctx, p)) < 0) +return ret; +return 0; +} + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -860,8 +873,8 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } } -static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, -int tile_byte_count, int x, int y, int w, int h) +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; AVPacket jpkt; @@ -913,7 +926,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return AVERROR_PATCHWELCOME; } -dst_offset = x + frame->linesize[0] * y / pixel_size; +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]; @@ -932,7 +945,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) +static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { TiffContext *s = avctx->priv_data; int tile_idx; @@ -945,6 +958,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int pos_x = 0, pos_y = 0; int ret; +s->jpgframe->width = s->tile_width; +s->jpgframe->height = s->tile_length; + +s->avctx_mjpeg->width = s->tile_width; +s->avctx_mjpeg->height = s->tile_length; + has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); @@ -981,7 +1000,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) bytestream2_seek(&s->gb, tile_offset, SEEK_SET); /* Decode JPEG tile and copy it in the reference frame */ -ret = dng_decode_jpeg_tile(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); +ret = dng_decode_jpeg(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); if (ret < 0) return ret; @@ -994,30 +1013,24 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) } } -return 0; -} +/* Frame is ready to be output */ +frame->pict_type = AV_PICTURE_TYPE_I; +frame->key_frame = 1; -static int dng_decode(AVCodecContext *avctx, AVFrame *frame, AVPacket *avpkt) { -int ret; +return avpkt->size; +} +static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) +{ TiffContext *s = avctx->priv_data; -s->jpgframe->width = s->tile_width; -s->jpgframe->height = s->tile_length; - -s->avctx_mjpeg->width = s->tile_width; -s->avctx_mjpeg->height = s->tile_length; - -/* Decode all tiles in a frame */ -ret = dng_decode_tiles(avctx, frame); -if (ret < 0) -return ret; +s->jpgframe->width = s->width; +s->jpgframe->height = s->height; -/* Frame is ready to be output */ -frame->pict_type = AV_PICTURE_TYPE_I; -frame->key_frame = 1; +s->avctx_mjpeg->width = s->width; +s->avctx_mjpeg->height = s->height; -return avpkt->size; +return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); } stat
[FFmpeg-devel] [PATCH v16 06/15] lavc/tiff: Fix edge case with full-length/width tiles
From: Nick Renieris When the height is equal to the tile length (full-height tile) after `height % tile_length` is applied with the current code, it results in the operating tile_length to be 0. This commit makes this leftover logic only applies if it's necessary. Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 78b4bd5301..3bf2b3e557 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -887,10 +887,14 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) int tile_byte_count_offset, tile_byte_count; int tile_count_x, tile_count_y; int tile_width, tile_length; +int has_width_leftover, has_height_leftover; int tile_x = 0, tile_y = 0; int pos_x = 0, pos_y = 0; int ret; +has_width_leftover = (s->width % s->tile_width != 0); +has_height_leftover = (s->height % s->tile_length != 0); + /* Calculate tile counts (round up) */ tile_count_x = (s->width + s->tile_width - 1) / s->tile_width; tile_count_y = (s->height + s->tile_length - 1) / s->tile_length; @@ -900,12 +904,12 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame) tile_x = tile_idx % tile_count_x; tile_y = tile_idx / tile_count_x; -if (tile_x == tile_count_x - 1) // If on the right edge +if (has_width_leftover && tile_x == tile_count_x - 1) // If on the right-most tile tile_width = s->width % s->tile_width; else tile_width = s->tile_width; -if (tile_y == tile_count_y - 1) // If on the bottom edge +if (has_height_leftover && tile_y == tile_count_y - 1) // If on the bottom-most tile tile_length = s->height % s->tile_length; else tile_length = s->tile_length; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 11/15] lavc/tiff: Decode 10-bit and 14-bit DNG images
From: Nick Renieris 10-bit sample: http://www.rawsamples.ch/raws/phones/RAW_ONEPLUS_ONE-A0001.DNG 14-bit sample: https://drive.google.com/open?id=0B4JyRT3Lth5HVndyOTVOdWktM3J4TFEydTk1MnY3RWlpSzVB Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 23 +++ 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index d0d045397d..61a140fe09 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -309,14 +309,19 @@ static void av_always_inline horizontal_fill(TiffContext *s, dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; } break; -case 12: { - uint16_t *dst16 = (uint16_t *)dst; - GetBitContext gb; - init_get_bits8(&gb, src, width); - for (int i = 0; i < s->width; i++) { - dst16[i] = get_bits(&gb, 12) << 4; - } - } +case 10: +case 12: +case 14: { +uint16_t *dst16 = (uint16_t *)dst; +int is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); +uint8_t shift = is_dng ? 0 : 16 - bpp; +GetBitContext gb; + +init_get_bits8(&gb, src, width); +for (int i = 0; i < s->width; i++) { +dst16[i] = get_bits(&gb, bpp) << shift; +} +} break; default: if (usePtr) { @@ -1067,7 +1072,9 @@ static int init_image(TiffContext *s, ThreadFrame *frame) return AVERROR_PATCHWELCOME; } break; +case 10101: case 10121: +case 10141: switch (AV_RL32(s->pattern)) { case 0x02010100: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 08/15] lavc/tiff: Force DNG pixel data endianness on an edge case
From: Nick Renieris This fixes "X7 RAW" and "X7 CinemaDNG" samples here: - https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 12 1 file changed, 12 insertions(+) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 28b8f42edd..b1d4c50e74 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1038,6 +1038,18 @@ static int init_image(TiffContext *s, ThreadFrame *frame) AV_RL32(s->pattern)); return AVERROR_PATCHWELCOME; } +/* Force endianness as mentioned in 'DNG Specification: Chapter 3: BitsPerSample' + NOTE: The spec actually specifies big-endian, not sure why we need little-endian, but + such images don't work otherwise. Examples are images produced by Zenmuse X7. */ +if ((s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) +&& (s->bpp != 8 && s->bpp != 16 && s->bpp != 32)) { +switch (s->avctx->pix_fmt) { +case AV_PIX_FMT_BAYER_RGGB16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16LE; break; +case AV_PIX_FMT_BAYER_BGGR16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16LE; break; +case AV_PIX_FMT_BAYER_GBRG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16LE; break; +case AV_PIX_FMT_BAYER_GRBG16BE: s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16LE; break; +} +} break; case 10161: switch (AV_RL32(s->pattern)) { -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 01/15] lavc/mjpegdec: Decode Huffman-coded lossless JPEGs embedded in DNGs
From: Nick Renieris Main image data in DNGs is usually comprised of tiles, each of which is a Huffman-encoded lossless JPEG. Tested for ljpeg regressions with: `ffmpeg -f lavfi -i testsrc=d=1 -vcodec ljpeg test.avi` `ffmpeg test.avi out.avi` The modified code in ljpeg_decode_rgb_scan runs without issues. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 52 +-- libavcodec/mjpegdec.h | 1 + 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index a65bc8df15..6391107f78 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,6 +412,14 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } +/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 + interleaved components and the width stored in their SOF3 markers is the + width of each one. We only output a single component, therefore we need + to adjust the output image width. */ +if (s->lossless == 1 && nb_components == 2) { +s->bayer = 1; +width *= 2; +} /* if different size, realloc/alloc picture */ if (width != s->width || height != s->height || bits != s->bits || @@ -488,6 +496,9 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) } switch (pix_fmt_id) { +case 0x: /* for bayer-encoded huffman lossless JPEGs embedded in DNGs */ +s->avctx->pix_fmt = AV_PIX_FMT_GRAY16LE; +break; case 0x1100: if (s->rgb) s->avctx->pix_fmt = s->bits <= 9 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_BGR48; @@ -1041,17 +1052,20 @@ static int handle_rstn(MJpegDecodeContext *s, int nb_components) return reset; } +/* Handles 1 to 4 components */ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int predictor, int point_transform) { int i, mb_x, mb_y; +unsigned width; uint16_t (*buffer)[4]; int left[4], top[4], topleft[4]; const int linesize = s->linesize[0]; const int mask = ((1 << s->bits) - 1) << point_transform; int resync_mb_y = 0; int resync_mb_x = 0; +int vpred[6]; -if (s->nb_components != 3 && s->nb_components != 4) +if (s->nb_components <= 0 || s->nb_components > 4) return AVERROR_INVALIDDATA; if (s->v_max != 1 || s->h_max != 1 || !s->lossless) return AVERROR_INVALIDDATA; @@ -1059,8 +1073,15 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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])); +if (s->restart_interval == 0) +s->restart_interval = INT_MAX; + +if (s->bayer) +width = s->mb_width / nb_components; /* Interleaved, width stored is the total so need to divide */ +else +width = s->mb_width; + +av_fast_malloc(&s->ljpeg_buffer, &s->ljpeg_buffer_size, width * 4 * sizeof(s->ljpeg_buffer[0][0])); if (!s->ljpeg_buffer) return AVERROR(ENOMEM); @@ -1078,7 +1099,12 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 ((mb_y * s->width) % s->restart_interval == 0) { +for (i = 0; i < 6; i++) +vpred[i] = 1 << (s->bits-1); +} + +for (mb_x = 0; mb_x < width; mb_x++) { int modified_predictor = predictor; if (get_bits_left(&s->gb) < 1) { @@ -1102,12 +1128,19 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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 == 0xF) return -1; +if (!s->bayer || mb_x) { +pred = left[i]; +} else { /* This path runs only for the first line in bayer images */ +vpred[i] += dc; +pred = vpred[i] - dc; +} + +PREDICT(pred, topleft[i], top[i], pred, modified_predictor); + left[i] = buffer[mb_x][i] = mask & (pred + (unsigned)(dc * (1 << point_transform))); } @@ -1151,6 +1184,11 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p ptr[
[FFmpeg-devel] [PATCH v16 02/15] lavc/tiff: Decode embedded JPEGs in DNG images
From: Nick Renieris Used a technique similar to lavc/tdsc.c for invoking the MJPEG decoder. This commit adds support for: - DNG tiles - DNG tile huffman lossless JPEG decoding - DNG 8-bpp ("packed" as dcraw calls it) decoding - DNG color scaling [1] - LinearizationTable tag - BlackLevel tag [1]: As specified in the DNG Specification - Chapter 5 Signed-off-by: Nick Renieris --- configure | 1 + libavcodec/Makefile | 2 +- libavcodec/tiff.c | 313 +++- libavcodec/tiff.h | 2 + 4 files changed, 310 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 34c2adb4a4..112b84f0ba 100755 --- a/configure +++ b/configure @@ -2817,6 +2817,7 @@ tdsc_decoder_deps="zlib" tdsc_decoder_select="mjpeg_decoder" theora_decoder_select="vp3_decoder" thp_decoder_select="mjpeg_decoder" +tiff_decoder_select="mjpeg_decoder" tiff_decoder_suggest="zlib lzma" tiff_encoder_suggest="zlib" truehd_decoder_select="mlp_parser" diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3cd73fbcc6..f814c69996 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -616,7 +616,7 @@ OBJS-$(CONFIG_TARGA_ENCODER) += targaenc.o rle.o OBJS-$(CONFIG_TARGA_Y216_DECODER) += targa_y216dec.o OBJS-$(CONFIG_TDSC_DECODER)+= tdsc.o OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o -OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o +OBJS-$(CONFIG_TIFF_DECODER)+= tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o mjpegdec.o OBJS-$(CONFIG_TIFF_ENCODER)+= tiffenc.o rle.o lzwenc.o tiff_data.o OBJS-$(CONFIG_TMV_DECODER) += tmv.o cga_data.o OBJS-$(CONFIG_TRUEHD_DECODER) += mlpdec.o mlpdsp.o diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index c520d7df83..4c6b835afe 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -35,6 +35,7 @@ #include "libavutil/attributes.h" #include "libavutil/avstring.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +47,7 @@ #include "mathops.h" #include "tiff.h" #include "tiff_data.h" +#include "mjpegdec.h" #include "thread.h" #include "get_bits.h" @@ -54,6 +56,10 @@ typedef struct TiffContext { AVCodecContext *avctx; GetByteContext gb; +/* JPEG decoding for DNG */ +AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG +AVFrame *jpgframe; // decoded JPEG tile + int get_subimage; uint16_t get_page; int get_thumbnail; @@ -76,7 +82,9 @@ typedef struct TiffContext { int is_bayer; uint8_t pattern[4]; +unsigned black_level; unsigned white_level; +const uint16_t *dng_lut; // Pointer to DNG linearization table uint32_t sub_ifd; uint16_t cur_page; @@ -86,6 +94,14 @@ typedef struct TiffContext { int stripsizesoff, stripsize, stripoff, strippos; LZWState *lzw; +/* Tile support */ +int is_tiled; +int tile_byte_counts_offset, tile_offsets_offset; +int tile_width, tile_length; +int tile_count; + +int is_jpeg; + uint8_t *deinvert_buf; int deinvert_buf_size; uint8_t *yuv_line; @@ -257,6 +273,9 @@ 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); + static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, int usePtr, const uint8_t *src, @@ -712,6 +731,204 @@ 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_raw_to_linear16(uint16_t value, +const uint16_t *lut, +uint16_t black_level, +float scale_factor) { +// Lookup table lookup +if (lut) +value = lut[value]; + +// Black level subtraction +value = av_clip_uint16_c((unsigned)value - black_level); + +// Color scaling +value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); + +return value; +} + +static uint16_t av_always_inline dng_raw_to_linear8(uint16_t value, +const uint16_t *lut, +uint1
[FFmpeg-devel] [PATCH v16 04/15] lavc/tiff: Apply color scaling to uncompressed DNGs
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 25 - 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index a2102f32b5..dd1295fad6 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -556,6 +556,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; +int is_dng; if (s->planar) width /= s->bppcount; @@ -657,6 +658,8 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid bytestream2_init(&s->gb, src, size); bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); +is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -679,6 +682,25 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid for (i = 0; i < width; i++) dst[i] = ff_reverse[src[i]]; } + +/* Color processing for DNG images with uncompressed strips (non-tiled) */ +if (is_dng) { +int is_u16, pixel_size_bytes, pixel_size_bits; + +is_u16 = (s->bpp > 8); +pixel_size_bits = (is_u16 ? 16 : 8); +pixel_size_bytes = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + +dng_blit(s, + dst, + 0, // no stride, only 1 line + dst, + 0, // no stride, only 1 line + width / pixel_size_bytes * pixel_size_bits / s->bpp * s->bppcount, // need to account for [1, 16] bpp + 1, + is_u16); +} + src += width; break; case TIFF_PACKBITS: @@ -1945,7 +1967,8 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } -if (s->is_bayer && s->white_level && s->bpp == 16) { +if (s->is_bayer && s->white_level && s->bpp == 16 && +!(s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG)) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 07/15] lavc/tiff: Don't apply strips-related logic to tiled images
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 42 ++ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 3bf2b3e557..28b8f42edd 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1780,7 +1780,7 @@ again: } } -if (!s->strippos && !s->stripoff) { +if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } @@ -1788,27 +1788,29 @@ again: if ((ret = init_image(s, &frame)) < 0) return ret; -if (s->strips == 1 && !s->stripsize) { -av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); -s->stripsize = avpkt->size - s->stripoff; -} +if (!s->is_tiled) { +if (s->strips == 1 && !s->stripsize) { +av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); +s->stripsize = avpkt->size - s->stripoff; +} -if (s->stripsizesoff) { -if (s->stripsizesoff >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, - avpkt->size - s->stripsizesoff); -} -if (s->strippos) { -if (s->strippos >= (unsigned)avpkt->size) -return AVERROR_INVALIDDATA; -bytestream2_init(&stripdata, avpkt->data + s->strippos, - avpkt->size - s->strippos); -} +if (s->stripsizesoff) { +if (s->stripsizesoff >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, +avpkt->size - s->stripsizesoff); +} +if (s->strippos) { +if (s->strippos >= (unsigned)avpkt->size) +return AVERROR_INVALIDDATA; +bytestream2_init(&stripdata, avpkt->data + s->strippos, +avpkt->size - s->strippos); +} -if (s->rps <= 0 || s->rps % s->subsampling[1]) { -av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); -return AVERROR_INVALIDDATA; +if (s->rps <= 0 || s->rps % s->subsampling[1]) { +av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); +return AVERROR_INVALIDDATA; +} } /* Handle DNG images with JPEG-compressed tiles */ -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 03/15] lavc/tiff: Convert DNGs to sRGB color space
From: Nick Renieris Signed-off-by: Nick Renieris --- libavcodec/tiff.c | 34 +++--- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 4c6b835afe..a2102f32b5 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -731,14 +731,23 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid return 0; } +static float av_always_inline linear_to_srgb(float value) { +if (value <= 0.0031308) +return value * 12.92; +else +return pow(value * 1.055, 1.0 / 2.4) - 0.055; +} + /** - * Map stored raw sensor values into linear reference values. - * See: DNG Specification - Chapter 5 + * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5) + * Then convert to sRGB color space. */ -static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, -const uint16_t *lut, -uint16_t black_level, -float scale_factor) { +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]; @@ -747,16 +756,19 @@ static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value, value = av_clip_uint16_c((unsigned)value - black_level); // Color scaling -value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) * 0x)); +value_norm = (float)value * scale_factor; + +// Color space conversion (sRGB) +value = av_clip_uint16_c((uint16_t)(linear_to_srgb(value_norm) * 0x)); return value; } -static uint16_t av_always_inline dng_raw_to_linear8(uint16_t 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_raw_to_linear16(value, lut, black_level, scale_factor) >> 8; +return dng_process_color16(value, lut, black_level, scale_factor) >> 8; } static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, @@ -774,7 +786,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, uint16_t *src_u16 = (uint16_t *)src; for (col = 0; col < width; col++) -*dst_u16++ = dng_raw_to_linear16(*src_u16++, s->dng_lut, s->black_level, scale_factor); +*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); @@ -782,7 +794,7 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, } else { for (line = 0; line < height; line++) { for (col = 0; col < width; col++) -*dst++ = dng_raw_to_linear8(*src++, s->dng_lut, s->black_level, scale_factor); +*dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); dst += dst_stride; src += src_stride; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 05/15] lavc/jpegtables: Handle multiple mappings to the same value
From: Nick Renieris Some JPEGs [1] have incorrect DHT entries that map 2 codes to the same value. The second (last) mapping does not ever actually appear in the code stream, therefore ignoring any mappings after the first one fixes this. Without this, an "mjpeg_decode_dc: bad vlc: 0:0" error is thrown. In all known files, the 2 codes are mapped to symbol 0 so only that case is checked. [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: https://www.dji.com/gr/zenmuse-x7/info#downloads Signed-off-by: Nick Renieris --- libavcodec/jpegtables.c | 17 ++--- libavcodec/tiff.c | 6 +++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index cbe5523cb4..fa5c6f9fc5 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -130,14 +130,25 @@ void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, { int i, j, k,nb, code, sym; -code = 0; +/* Some badly encoded files [1] map 2 different codes to symbol 0. + Only the first one is valid, so we zero-initialize this here and + make sure we only set it once (the first time) in the loop below. + + [1]: Embedded JPEGs in "X7 RAW" and "X7 CinemaDNG" samples here: +https://www.dji.com/gr/zenmuse-x7/info#downloads + */ +huff_size[0] = 0; + k = 0; +code = 0; for(i=1;i<=16;i++) { nb = bits_table[i]; for(j=0;jhttps://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 10/15] lavc/tiff: Support decoding of DNGs with single-component JPEGs
From: Nick Renieris 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 --- libavcodec/tiff.c | 61 +++ 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 511c057734..d0d045397d 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 * s->bppcount, // 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_
[FFmpeg-devel] [PATCH v16 09/15] lavc/mjpegdec: Enable decoding of single-component bayer images
From: Nick Renieris Also, ensure no false positives when determining DNG bayer images, by setting them in tiff.c instead of relying on a heuristic. There's no way to determine this just from the JPEG data, so we have to pass this information from outside the MJPEG decoder. Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 32 +--- libavcodec/tiff.c | 7 +++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 6391107f78..0a920a7144 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -412,13 +412,17 @@ int ff_mjpeg_decode_sof(MJpegDecodeContext *s) return AVERROR_PATCHWELCOME; } -/* Lossless JPEGs encoded in DNGs are commonly bayer-encoded. They contain 2 - interleaved components and the width stored in their SOF3 markers is the - width of each one. We only output a single component, therefore we need - to adjust the output image width. */ -if (s->lossless == 1 && nb_components == 2) { -s->bayer = 1; -width *= 2; +if (s->bayer) { +if (nb_components == 2) { +/* Bayer images embedded in DNGs can contain 2 interleaved components and the + width stored in their SOF3 markers is the width of each one. We only output + a single component, therefore we need to adjust the output image width. We + handle the deinterleaving (but not the debayering) in this file. */ +width *= 2; +} +/* They can also contain 1 component, which is double the width and half the height +of the final image (rows are interleaved). We don't handle the decoding in this +file, but leave that to the TIFF/DNG decoder. */ } /* if different size, realloc/alloc picture */ @@ -1184,10 +1188,16 @@ static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int nb_components, int p 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->bayer && nb_components == 2) { -for (mb_x = 0; mb_x < width; mb_x++) { -((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; -((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} else if (s->bayer) { +if (nb_components == 1) { +/* Leave decoding to the TIFF/DNG decoder (see comment in ff_mjpeg_decode_sof) */ +for (mb_x = 0; mb_x < width; mb_x++) +((uint16_t*)ptr)[mb_x] = buffer[mb_x][0]; +} else if (nb_components == 2) { +for (mb_x = 0; mb_x < width; mb_x++) { +((uint16_t*)ptr)[2*mb_x + 0] = buffer[mb_x][0]; +((uint16_t*)ptr)[2*mb_x + 1] = buffer[mb_x][1]; +} } } else { for(i=0; igb.buffer; 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, &jpkt); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH v16 12/15] lavc/mjpegdec: Skip unknown APPx marker on bayer images
From: Nick Renieris Samples: - Embedded JPEG images in the DNG images here: https://www.photographyblog.com/previews/pentax_k1_photos Signed-off-by: Nick Renieris --- libavcodec/mjpegdec.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 0a920a7144..1f2fabe2df 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1807,8 +1807,15 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) int len, id, i; len = get_bits(&s->gb, 16); -if (len < 6) -return AVERROR_INVALIDDATA; +if (len < 6) { +if (s->bayer) { +// Pentax K-1 (digital camera) JPEG images embedded in DNG images contain unknown APP0 markers +av_log(s->avctx, AV_LOG_WARNING, "skipping APPx (len=%"PRId32") for bayer-encoded image\n", len); +skip_bits(&s->gb, len); +return 0; +} else +return AVERROR_INVALIDDATA; +} if (8 * len > get_bits_left(&s->gb)) return AVERROR_INVALIDDATA; -- 2.21.0.windows.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH v16 05/15] lavc/jpegtables: Handle multiple mappings to the same value
Στις Πέμ, 29 Αυγ 2019 στις 4:00 μ.μ., ο/η Michael Niedermayer έγραψε: > This looks unrelated Messed up when rebasing, will fix in a bit. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".