From 801b636633ea80e15af4f22d148b2981f573d739 Mon Sep 17 00:00:00 2001 From: Peter Ross Date: Sun, 6 Jan 2013 14:15:25 +1100 Subject: wtvenc: mux thumbnail picture --- libavformat/wtvenc.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 5 deletions(-) (limited to 'libavformat/wtvenc.c') diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c index 304bd14f74..22917a454c 100644 --- a/libavformat/wtvenc.c +++ b/libavformat/wtvenc.c @@ -103,6 +103,8 @@ typedef struct { int64_t last_pts; int64_t last_serial; + + AVPacket thumbnail; } WtvContext; @@ -378,6 +380,8 @@ static int write_header(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; + if (st->codec->codec_id == AV_CODEC_ID_MJPEG) + continue; ret = write_stream_codec(s, st); if (ret < 0) { av_log(s, AV_LOG_ERROR, "write stream codec failed codec_type(0x%x)\n", st->codec->codec_type); @@ -389,6 +393,8 @@ static int write_header(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; + if (st->codec->codec_id == AV_CODEC_ID_MJPEG) + continue; ret = write_stream_data(s, st); if (ret < 0) { av_log(s, AV_LOG_ERROR, "write stream data failed codec_type(0x%x)\n", st->codec->codec_type); @@ -425,6 +431,11 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; WtvContext *wctx = s->priv_data; + if (s->streams[pkt->stream_index]->codec->codec_id == AV_CODEC_ID_MJPEG && !wctx->thumbnail.size) { + av_copy_packet(&wctx->thumbnail, pkt); + return 0; + } + /* 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); @@ -590,27 +601,66 @@ static void write_table_entries_time(AVFormatContext *s) avio_wl64(pb, wctx->last_serial); } -static void write_tag(AVIOContext *pb, const char *key, const char *value) +static void write_metadata_header(AVIOContext *pb, int type, const char *key, int value_size) { ff_put_guid(pb, &ff_metadata_guid); - avio_wl32(pb, 1); - avio_wl32(pb, strlen(value)*2 + 2); + avio_wl32(pb, type); + avio_wl32(pb, value_size); avio_put_str16le(pb, key); +} + +static int metadata_header_size(const char *key) +{ + return 16 + 4 + 4 + strlen(key)*2 + 2; +} + +static void write_tag_int32(AVIOContext *pb, const char *key, int value) +{ + write_metadata_header(pb, 0, key, 4); + avio_wl32(pb, value); +} + +static void write_tag(AVIOContext *pb, const char *key, const char *value) +{ + write_metadata_header(pb, 1, key, strlen(value)*2 + 2); avio_put_str16le(pb, value); } +static int attachment_value_size(const AVPacket *pkt, const AVDictionaryEntry *e) +{ + return strlen("image/jpeg")*2 + 2 + 1 + (e ? strlen(e->value)*2 : 0) + 2 + 4 + pkt->size; +} + static void write_table_entries_attrib(AVFormatContext *s) { + WtvContext *wctx = s->priv_data; + AVIOContext *pb = s->pb; AVDictionaryEntry *tag = 0; //FIXME: translate special tags (e.g. WM/Bitrate) to binary representation ff_metadata_conv(&s->metadata, ff_asf_metadata_conv, NULL); while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) - write_tag(s->pb, tag->key, tag->value); + write_tag(pb, tag->key, tag->value); + + if (wctx->thumbnail.size) { + AVStream *st = s->streams[wctx->thumbnail.stream_index]; + tag = av_dict_get(st->metadata, "title", NULL, 0); + write_metadata_header(pb, 2, "WM/Picture", attachment_value_size(&wctx->thumbnail, tag)); + + avio_put_str16le(pb, "image/jpeg"); + avio_w8(pb, 0x10); + avio_put_str16le(pb, tag ? tag->value : ""); + + avio_wl32(pb, wctx->thumbnail.size); + avio_write(pb, wctx->thumbnail.data, wctx->thumbnail.size); + + write_tag_int32(pb, "WM/MediaThumbType", 2); + } } static void write_table_redirector_legacy_attrib(AVFormatContext *s) { + WtvContext *wctx = s->priv_data; AVIOContext *pb = s->pb; AVDictionaryEntry *tag = 0; int64_t pos = 0; @@ -618,7 +668,16 @@ static void write_table_redirector_legacy_attrib(AVFormatContext *s) //FIXME: translate special tags to binary representation while ((tag = av_dict_get(s->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) { avio_wl64(pb, pos); - pos += 16 + 4 + 4 + strlen(tag->key)*2 + 2 + strlen(tag->value)*2 + 2; + pos += metadata_header_size(tag->key) + strlen(tag->value)*2 + 2; + } + + if (wctx->thumbnail.size) { + AVStream *st = s->streams[wctx->thumbnail.stream_index]; + avio_wl64(pb, pos); + pos += metadata_header_size("WM/Picture") + attachment_value_size(&wctx->thumbnail, av_dict_get(st->metadata, "title", NULL, 0)); + + avio_wl64(pb, pos); + pos += metadata_header_size("WM/MediaThumbType") + 4; } } @@ -732,6 +791,7 @@ static int write_trailer(AVFormatContext *s) av_free(wctx->sp_pairs); av_free(wctx->st_pairs); + av_free_packet(&wctx->thumbnail); return 0; } -- cgit v1.2.1