[FFmpeg-cvslog] wtvenc: produce seekable files
Peter Ross
git at videolan.org
Wed Nov 7 14:02:55 CET 2012
ffmpeg | branch: master | Peter Ross <pross at xvid.org> | Wed Nov 7 16:52:33 2012 +1100| [a373f352728c5f56b6679ea8ab668d830811c324] | committer: Michael Niedermayer
wtvenc: produce seekable files
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a373f352728c5f56b6679ea8ab668d830811c324
---
libavformat/wtvenc.c | 78 ++++++++++++++++++++++++++++++++++++++++++-----
tests/ref/lavf/wtv | 2 +-
tests/ref/seek/lavf_wtv | 31 +++++++++++--------
3 files changed, 91 insertions(+), 20 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
diff --git a/tests/ref/seek/lavf_wtv b/tests/ref/seek/lavf_wtv
index d69c293..67def8a 100644
--- a/tests/ref/seek/lavf_wtv
+++ b/tests/ref/seek/lavf_wtv
@@ -1,41 +1,48 @@
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
ret: 0 st:-1 flags:0 ts:-1.000000
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
-ret:-1 st:-1 flags:1 ts: 1.894167
+ret: 0 st:-1 flags:1 ts: 1.894167
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret: 0 st: 0 flags:0 ts: 0.788334
-ret: 0 st: 1 flags:1 dts: 0.772766 pts: 0.772766 pos: 320800 size: 209
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret: 0 st: 0 flags:1 ts:-0.317499
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
ret:-1 st: 1 flags:0 ts: 2.576668
-ret:-1 st: 1 flags:1 ts: 1.470835
+ret: 0 st: 1 flags:1 ts: 1.470835
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret: 0 st:-1 flags:0 ts: 0.365002
-ret: 0 st: 1 flags:1 dts: 0.380930 pts: 0.380930 pos: 167000 size: 209
+ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
ret: 0 st:-1 flags:1 ts:-0.740831
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
ret:-1 st: 0 flags:0 ts: 2.153336
-ret:-1 st: 0 flags:1 ts: 1.047503
+ret: 0 st: 0 flags:1 ts: 1.047503
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret: 0 st: 1 flags:0 ts:-0.058330
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
-ret:-1 st: 1 flags:1 ts: 2.835837
+ret: 0 st: 1 flags:1 ts: 2.835837
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret:-1 st:-1 flags:0 ts: 1.730004
ret: 0 st:-1 flags:1 ts: 0.624171
-ret: 0 st: 1 flags:1 dts: 0.616032 pts: 0.616032 pos: 266144 size: 209
+ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
ret: 0 st: 0 flags:0 ts:-0.481662
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
-ret:-1 st: 0 flags:1 ts: 2.412505
+ret: 0 st: 0 flags:1 ts: 2.412505
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret:-1 st: 1 flags:0 ts: 1.306672
ret: 0 st: 1 flags:1 ts: 0.200839
ret: 0 st: 1 flags:1 dts: 0.224195 pts: 0.224195 pos: 112904 size: 209
ret: 0 st:-1 flags:0 ts:-0.904994
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
-ret:-1 st:-1 flags:1 ts: 1.989173
+ret: 0 st:-1 flags:1 ts: 1.989173
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret: 0 st: 0 flags:0 ts: 0.883340
-ret: 0 st: 1 flags:1 dts: 0.903379 pts: 0.903379 pos: 357632 size: 209
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret: 0 st: 0 flags:1 ts:-0.222493
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
ret:-1 st: 1 flags:0 ts: 2.671674
-ret:-1 st: 1 flags:1 ts: 1.565841
+ret: 0 st: 1 flags:1 ts: 1.565841
+ret: 0 st: 1 flags:1 dts: 0.694399 pts: 0.694399 pos: 294744 size: 209
ret: 0 st:-1 flags:0 ts: 0.460008
-ret: 0 st: 1 flags:1 dts: 0.459297 pts: 0.459297 pos: 205328 size: 209
+ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
ret: 0 st:-1 flags:1 ts:-0.645825
ret: 0 st: 1 flags:1 dts:-0.010907 pts:-0.010907 pos: 26344 size: 208
More information about the ffmpeg-cvslog
mailing list