[FFmpeg-devel] [PATCH 5/5] wtvenc: produce seekable files

Peter Ross pross at xvid.org
Wed Nov 7 06:52:33 CET 2012


---
 libavformat/wtvenc.c |   78 +++++++++++++++++++++++++++++++++++++++++++++-----
 tests/ref/lavf/wtv   |    2 +-
 2 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c
index 9108bc0..9cc5a05 100644
--- a/libavformat/wtvenc.c
+++ b/libavformat/wtvenc.c
@@ -80,17 +80,43 @@ typedef struct {
 } WtvChunkEntry;
 
 typedef struct {
+    int64_t serial;
+    int64_t value;
+} WtvSyncEntry;
+
+typedef struct {
     int64_t timeline_start_pos;
     WtvFile file[WTV_FILES];
     int64_t serial;         /** chunk serial number */
     int64_t last_chunk_pos; /** last chunk position */
+    int64_t last_timestamp_pos; /** last timestamp chunk position */
+    int64_t first_index_pos;    /** first index_chunk position */
 
     WtvChunkEntry index[MAX_NB_INDEX];
     int nb_index;
     int first_video_flag;
-    int64_t sync_pos;
+
+    WtvSyncEntry *st_pairs; /* (serial, timestamp) pairs */
+    int nb_st_pairs;
+    WtvSyncEntry *sp_pairs; /* (serial, position) pairs */
+    int nb_sp_pairs;
+
+    int64_t last_pts;
+    int64_t last_serial;
 } WtvContext;
 
+
+static void add_serial_pair(WtvSyncEntry ** list, int * count, int64_t serial, int64_t value)
+{
+    int new_count = *count + 1;
+    WtvSyncEntry *new_list = av_realloc(*list, new_count * sizeof(WtvSyncEntry));
+    if (!new_list)
+        return;
+    new_list[*count] = (WtvSyncEntry){serial, value};
+    *list  = new_list;
+    *count = new_count;
+}
+
 typedef int WTVHeaderWriteFunc(AVIOContext *pb);
 
 typedef struct {
@@ -186,6 +212,9 @@ static void write_index(AVFormatContext *s)
     }
     wctx->nb_index = 0;   // reset index
     finish_chunk_noindex(s);
+
+    if (!wctx->first_index_pos)
+        wctx->first_index_pos = wctx->last_chunk_pos;
 }
 
 static void finish_chunk(AVFormatContext *s)
@@ -277,12 +306,14 @@ static void write_sync(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     WtvContext *wctx = s->priv_data;
     int64_t last_chunk_pos = wctx->last_chunk_pos;
-    wctx->sync_pos = avio_tell(pb) - wctx->timeline_start_pos;
 
     write_chunk_header(s, &ff_sync_guid, 0x18, 0);
-    write_pad(pb, 24);
+    avio_wl64(pb, wctx->first_index_pos);
+    avio_wl64(pb, wctx->last_timestamp_pos);
+    avio_wl64(pb, 0);
 
     finish_chunk(s);
+    add_serial_pair(&wctx->sp_pairs, &wctx->nb_sp_pairs, wctx->serial, wctx->last_chunk_pos);
 
     wctx->last_chunk_pos = last_chunk_pos;
 }
@@ -317,6 +348,9 @@ static int write_header(AVFormatContext *s)
     int i, pad, ret;
     AVStream *st;
 
+    wctx->last_chunk_pos     = -1;
+    wctx->last_timestamp_pos = -1;
+
     ff_put_guid(pb, &ff_wtv_guid);
     ff_put_guid(pb, &sub_wtv_guid);
 
@@ -335,6 +369,7 @@ static int write_header(AVFormatContext *s)
 
     pad = (1 << WTV_SECTOR_BITS) - avio_tell(pb);
     write_pad(pb, pad);
+
     wctx->timeline_start_pos = avio_tell(pb);
 
     wctx->serial = 1;
@@ -381,6 +416,8 @@ static void write_timestamp(AVFormatContext *s, AVPacket *pkt)
     avio_wl64(pb, 0);
     avio_wl64(pb, enc->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY) ? 1 : 0);
     avio_wl64(pb, 0);
+
+    wctx->last_timestamp_pos = wctx->last_chunk_pos;
 }
 
 static int write_packet(AVFormatContext *s, AVPacket *pkt)
@@ -388,6 +425,19 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
     AVIOContext *pb = s->pb;
     WtvContext  *wctx = s->priv_data;
 
+    /* emit sync chunk and 'timeline.table.0.entries.Event' record every 50 frames */
+    if (wctx->serial - (wctx->nb_sp_pairs ? wctx->sp_pairs[wctx->nb_sp_pairs - 1].serial : 0) >= 50)
+        write_sync(s);
+
+    /* emit 'table.0.entries.time' record every 500ms */
+    if (pkt->pts != AV_NOPTS_VALUE && pkt->pts - (wctx->nb_st_pairs ? wctx->st_pairs[wctx->nb_st_pairs - 1].value : 0) >= 5000000)
+        add_serial_pair(&wctx->st_pairs, &wctx->nb_st_pairs, wctx->serial, pkt->pts);
+
+    if (pkt->pts != AV_NOPTS_VALUE && pkt->pts > wctx->last_pts) {
+        wctx->last_pts = pkt->pts;
+        wctx->last_serial = wctx->serial;
+    }
+
     // write timestamp chunk
     write_timestamp(s, pkt);
 
@@ -520,10 +570,24 @@ static void write_table_entries_events(AVFormatContext *s)
 {
     AVIOContext *pb = s->pb;
     WtvContext *wctx = s->priv_data;
+    int i;
+    for (i = 0; i < wctx->nb_sp_pairs; i++) {
+        avio_wl64(pb, wctx->sp_pairs[i].serial);
+        avio_wl64(pb, wctx->sp_pairs[i].value);
+    }
+}
 
-    //FIXME: output frame_nb, position pairs.
-    //We only set the first sync_chunk position here.
-    avio_wl64(pb, 0x2);   avio_wl64(pb, wctx->sync_pos);
+static void write_table_entries_time(AVFormatContext *s)
+{
+    AVIOContext *pb = s->pb;
+    WtvContext *wctx = s->priv_data;
+    int i;
+    for (i = 0; i < wctx->nb_st_pairs; i++) {
+        avio_wl64(pb, wctx->st_pairs[i].value);
+        avio_wl64(pb, wctx->st_pairs[i].serial);
+    }
+    avio_wl64(pb, wctx->last_pts);
+    avio_wl64(pb, wctx->last_serial);
 }
 
 static void write_tag(AVIOContext *pb, const char *key, const char *value)
@@ -648,7 +712,7 @@ static int write_trailer(AVFormatContext *s)
         return -1;
 
     start_pos = avio_tell(pb);
-    //FIXME: output timestamp, frame_nb pairs here.
+    write_table_entries_time(s);
     if (finish_file(s, WTV_TABLE_0_ENTRIES_TIME, start_pos) < 0)
         return -1;
 
diff --git a/tests/ref/lavf/wtv b/tests/ref/lavf/wtv
index 0aaa01a..8f2c2ac 100644
--- a/tests/ref/lavf/wtv
+++ b/tests/ref/lavf/wtv
@@ -1,3 +1,3 @@
-dcb02f245dca4597704cbfc06e7eb543 *./tests/data/lavf/lavf.wtv
+345516d3a03fd239c62e5e7257c9f4a2 *./tests/data/lavf/lavf.wtv
 413696 ./tests/data/lavf/lavf.wtv
 ./tests/data/lavf/lavf.wtv CRC=0xcc2dc628
-- 
1.7.10.4

-- Peter
(A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121107/5ee35d0c/attachment.asc>


More information about the ffmpeg-devel mailing list