diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c index 9108bc0013..9cc5a05708 100644 --- a/libavformat/wtvenc.c +++ b/libavformat/wtvenc.c @@ -79,18 +79,44 @@ typedef struct { int stream_id; } 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 0aaa01a0ed..8f2c2acc6c 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 d69c29358a..67def8aae3 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