[FFmpeg-devel] [PATCH] AVI metadata retrieval improvements

Thilo Borgmann thilo.borgmann at mail.de
Thu Mar 20 23:12:27 CET 2014


Am 04.03.14 17:16, schrieb gregory.wolfe at kodakalaris.com:
> This is the second of two changes I've made as part of our upgrade to
> the latest FFmpeg development branch.
> 
> This patch enhances two aspects of metadata retrieval from AVI files.
> I've attached before/after command line output from ffmpeg for each
> modification.  Test video files that can be used to generate the
> before/after output have been uploaded to the FFmpeg FTP server.
> 
> 
> Patched file:  libavformat/avidec.c
> Description (from commit message):
> 
> Added function avi_extract_stream_metadata().  Some cameras (e.g., Fuji)
> store stream metadata following the "strd" stream data tag.  Currently,
> avi_read_header() calls ff_get_extradata() to read and save this data in
> the codec's "extradata" slot.  This new function extracts metadata from
> "extradata" by first looking for the AVIF tag, then extracting metadata
> from the EXIF tags which follow it.

I've rewritten almost everything to use existing EXIF functions.

Patch attached, but there are 2 issues I need advise for:

a) Current EXIF is in lavc only and relies on lavc/tiff.h and lavc/bytestream,
so these have to be moved (to lavu)?

b) I can't see anything about the endianess in AVI files. How to determine or is
it always little-endian?


> In a separate change, some cameras (e.g., Casio) store the date format as
> yyyy/mm/dd/ hh:mm.  Added code to get rid of the "/" following "dd".

I don't think this is a good idea for FFmpeg to change the metadata. Should be
done by the interpreting application, IMHO.

Please comment.

-Thilo

-------------- next part --------------
>From 9b0cdb9de77ca90aeffba43aa82ee949c5b28e8c Mon Sep 17 00:00:00 2001
From: Thilo Borgmann <thilo.borgmann at mail.de>
Date: Thu, 20 Mar 2014 23:02:41 +0100
Subject: [PATCH] lavf/avidec: Read metadata EXIF tags from AVIF tag. Based on
 patch by Gregory Wolfe (Kodak Alaris) <gregory.wolfe at kodakalaris.com>.

---
 libavformat/avidec.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 0a837d4..699bfea 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -34,6 +34,9 @@
 #include "dv.h"
 #include "internal.h"
 #include "riff.h"
+#include "libavcodec/bytestream.h"
+#include "libavcodec/tiff.h"
+#include "libavcodec/exif.h"
 
 typedef struct AVIStream {
     int64_t frame_offset;   /* current frame (video) or byte (audio) counter
@@ -379,6 +382,44 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end)
     }
 }
 
+static int avi_extract_stream_metadata(AVStream *st)
+{
+    GetByteContext gb;
+    uint8_t *data = st->codec->extradata;
+    int data_size = st->codec->extradata_size;
+    int tag, offset, le = 1;
+
+    if ((data == 0) || (data_size < 8)) {
+        return AVERROR_INVALIDDATA;
+    }
+
+    // XXX bytestream2 from libavcodec...
+    bytestream2_init(&gb, data, data_size);
+
+    tag = ff_tget_long(&gb, le); // XXX init le = 1?
+
+    switch (tag) {
+    case MKTAG('A', 'V', 'I', 'F'):
+        // skip 4 byte padding
+        bytestream2_skip(&gb, 4);
+        offset = bytestream2_tell(&gb);
+        bytestream2_init(&gb, data + offset, data_size - offset);
+
+        return ff_exif_decode_ifd(st->codec, &gb, le, 0, &st->metadata);
+        break;
+    case MKTAG('C', 'A', 'S', 'I'):
+        avpriv_request_sample(st->codec, "RIFF stream data tag type CASI (%u)", tag);
+        break;
+    case MKTAG('Z', 'o', 'r', 'a'):
+        avpriv_request_sample(st->codec, "RIFF stream data tag type Zora (%u)", tag);
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
 static int calculate_bitrate(AVFormatContext *s)
 {
     AVIContext *avi = s->priv_data;
@@ -821,7 +862,7 @@ static int avi_read_header(AVFormatContext *s)
                 if (cur_pos < list_end)
                     size = FFMIN(size, list_end - cur_pos);
                 st = s->streams[stream_index];
-
+                if (st) {
                 if (size<(1<<30)) {
                     if (ff_get_extradata(st->codec, pb, size) < 0)
                         return AVERROR(ENOMEM);
@@ -829,6 +870,12 @@ static int avi_read_header(AVFormatContext *s)
 
                 if (st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly
                     avio_r8(pb);
+
+                ret = avi_extract_stream_metadata(st);
+                if (ret < 0) {
+                    av_log(s, AV_LOG_WARNING, "could not decoding EXIF data in stream header.\n");
+                }
+                }
             }
             break;
         case MKTAG('i', 'n', 'd', 'x'):
-- 
1.8.3.2



More information about the ffmpeg-devel mailing list