avcodec/mjpegdec: Read EXIF metadata in JPEG input.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
		
							parent
							
								
									ad0f7574ef
								
							
						
					
					
						commit
						bb4e1b4cf9
					
				| @ -14,6 +14,7 @@ version <next> | ||||
| - ffmpeg -t option can now be used for inputs, to limit the duration of | ||||
|   data read from an input file | ||||
| - incomplete Voxware MetaSound decoder | ||||
| - read EXIF metadata from JPEG | ||||
| 
 | ||||
| 
 | ||||
| version 2.0: | ||||
|  | ||||
| @ -267,7 +267,7 @@ OBJS-$(CONFIG_METASOUND_DECODER)       += metasound.o metasound_data.o \ | ||||
|                                           twinvq.o | ||||
| OBJS-$(CONFIG_MICRODVD_DECODER)        += microdvddec.o ass.o | ||||
| OBJS-$(CONFIG_MIMIC_DECODER)           += mimic.o | ||||
| OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o mjpeg.o | ||||
| OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o mjpeg.o exif.o tiff_common.o | ||||
| OBJS-$(CONFIG_MJPEG_ENCODER)           += mjpegenc.o mjpeg.o | ||||
| OBJS-$(CONFIG_MJPEGB_DECODER)          += mjpegbdec.o mjpegdec.o mjpeg.o | ||||
| OBJS-$(CONFIG_MLP_DECODER)             += mlpdec.o mlpdsp.o | ||||
|  | ||||
| @ -39,6 +39,9 @@ | ||||
| #include "mjpeg.h" | ||||
| #include "mjpegdec.h" | ||||
| #include "jpeglsdec.h" | ||||
| #include "tiff.h" | ||||
| #include "exif.h" | ||||
| #include "bytestream.h" | ||||
| 
 | ||||
| 
 | ||||
| static int build_vlc(VLC *vlc, const uint8_t *bits_table, | ||||
| @ -1493,6 +1496,43 @@ static int mjpeg_decode_app(MJpegDecodeContext *s) | ||||
|         goto out; | ||||
|     } | ||||
| 
 | ||||
|     /* EXIF metadata */ | ||||
|     if (s->start_code == APP1 && id == AV_RB32("Exif")) { | ||||
|         GetByteContext gbytes; | ||||
|         int ret, le, ifd_offset, bytes_read; | ||||
|         const uint8_t *aligned; | ||||
| 
 | ||||
|         skip_bits(&s->gb, 16); // skip padding
 | ||||
|         len -= 2; | ||||
| 
 | ||||
|         // init byte wise reading
 | ||||
|         aligned = align_get_bits(&s->gb); | ||||
|         bytestream2_init(&gbytes, aligned, len); | ||||
| 
 | ||||
|         // read TIFF header
 | ||||
|         ret = ff_tdecode_header(&gbytes, &le, &ifd_offset); | ||||
|         if (ret) { | ||||
|             av_log(s->avctx, AV_LOG_ERROR, "mjpeg: invalid TIFF header in EXIF data\n"); | ||||
|             return ret; | ||||
|         } | ||||
| 
 | ||||
|         bytestream2_seek(&gbytes, ifd_offset, SEEK_SET); | ||||
| 
 | ||||
|         // read 0th IFD and store the metadata
 | ||||
|         // (return values > 0 indicate the presence of subimage metadata)
 | ||||
|         ret = ff_exif_decode_ifd(s->avctx, &gbytes, le, 0, &s->exif_metadata); | ||||
|         if (ret < 0) { | ||||
|             av_log(s->avctx, AV_LOG_ERROR, "mjpeg: error decoding EXIF data\n"); | ||||
|             return ret; | ||||
|         } | ||||
| 
 | ||||
|         bytes_read = bytestream2_tell(&gbytes); | ||||
|         skip_bits(&s->gb, bytes_read << 3); | ||||
|         len -= bytes_read; | ||||
| 
 | ||||
|         goto out; | ||||
|     } | ||||
| 
 | ||||
|     /* Apple MJPEG-A */ | ||||
|     if ((s->start_code == APP1) && (len > (0x28 - 8))) { | ||||
|         id   = get_bits_long(&s->gb, 32); | ||||
| @ -1688,6 +1728,8 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, | ||||
|     int i, index; | ||||
|     int ret = 0; | ||||
| 
 | ||||
|     av_dict_free(&s->exif_metadata); | ||||
| 
 | ||||
|     buf_ptr = buf; | ||||
|     buf_end = buf + buf_size; | ||||
|     while (buf_ptr < buf_end) { | ||||
| @ -1916,6 +1958,9 @@ the_end: | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     av_dict_copy(avpriv_frame_get_metadatap(data), s->exif_metadata, 0); | ||||
|     av_dict_free(&s->exif_metadata); | ||||
| 
 | ||||
|     av_log(avctx, AV_LOG_DEBUG, "decode frame unused %td bytes\n", | ||||
|            buf_end - buf_ptr); | ||||
| //  return buf_end - buf_ptr;
 | ||||
| @ -1942,6 +1987,7 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) | ||||
|         av_freep(&s->blocks[i]); | ||||
|         av_freep(&s->last_nnz[i]); | ||||
|     } | ||||
|     av_dict_free(&s->exif_metadata); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -119,6 +119,7 @@ typedef struct MJpegDecodeContext { | ||||
|     unsigned int ljpeg_buffer_size; | ||||
| 
 | ||||
|     int extern_huff; | ||||
|     AVDictionary *exif_metadata; | ||||
| } MJpegDecodeContext; | ||||
| 
 | ||||
| int ff_mjpeg_decode_init(AVCodecContext *avctx); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user