aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2016-02-03 03:42:50 +0100
committerMarton Balint <cus@passwd.hu>2016-02-05 21:32:14 +0100
commit79e42936137a535a8bac8ff3174c3658ce52a482 (patch)
tree8ae12d87c1c1ed18e8228eb9b42ff22ddcad9dda
parent046476730102da3fe795176c9738e4db6bc7036f (diff)
downloadffmpeg-79e42936137a535a8bac8ff3174c3658ce52a482.tar.gz
lavf/asfenc: add support for storing languages
Checked compatiblity with VLC, Windows Media Player 12 and Windows Media ASF Viewer 9 series. Reviewed-by: Michael Niedermayer <michael@niedermayer.cc> Signed-off-by: Marton Balint <cus@passwd.hu>
-rw-r--r--libavformat/asf.c4
-rw-r--r--libavformat/asf.h1
-rw-r--r--libavformat/asfenc.c73
3 files changed, 74 insertions, 4 deletions
diff --git a/libavformat/asf.c b/libavformat/asf.c
index 80d24dbf43..455ca4d826 100644
--- a/libavformat/asf.c
+++ b/libavformat/asf.c
@@ -143,6 +143,10 @@ const ff_asf_guid ff_asf_digital_signature = {
0xfc, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e
};
+const ff_asf_guid ff_asf_extended_stream_properties_object = {
+ 0xcb, 0xa5, 0xe6, 0x14, 0x72, 0xc6, 0x32, 0x43, 0x83, 0x99, 0xa9, 0x69, 0x52, 0x06, 0x5b, 0x5a
+};
+
/* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */
const AVMetadataConv ff_asf_metadata_conv[] = {
{ "WM/AlbumArtist", "album_artist" },
diff --git a/libavformat/asf.h b/libavformat/asf.h
index f98fc46edc..1070293b77 100644
--- a/libavformat/asf.h
+++ b/libavformat/asf.h
@@ -101,6 +101,7 @@ extern const ff_asf_guid ff_asf_language_guid;
extern const ff_asf_guid ff_asf_content_encryption;
extern const ff_asf_guid ff_asf_ext_content_encryption;
extern const ff_asf_guid ff_asf_digital_signature;
+extern const ff_asf_guid ff_asf_extended_stream_properties_object;
extern const AVMetadataConv ff_asf_metadata_conv[];
diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c
index 6932c11250..e2aa2e00ba 100644
--- a/libavformat/asfenc.c
+++ b/libavformat/asfenc.c
@@ -23,6 +23,7 @@
#include "libavutil/dict.h"
#include "libavutil/mathematics.h"
#include "avformat.h"
+#include "avlanguage.h"
#include "avio_internal.h"
#include "internal.h"
#include "riff.h"
@@ -220,6 +221,8 @@ typedef struct ASFContext {
uint32_t seqno;
int is_streamed;
ASFStream streams[128]; ///< it's max number and it's not that big
+ const char *languages[128];
+ int nb_languages;
/* non streamed additonnal info */
uint64_t nb_packets; ///< how many packets are there in the file, invalid if broadcasting
int64_t duration; ///< in 100ns units
@@ -403,6 +406,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
bit_rate = 0;
for (n = 0; n < s->nb_streams; n++) {
+ AVDictionaryEntry *entry;
enc = s->streams[n]->codec;
avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */
@@ -412,6 +416,27 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
&& enc->sample_aspect_ratio.num > 0
&& enc->sample_aspect_ratio.den > 0)
has_aspect_ratio++;
+
+ entry = av_dict_get(s->streams[n]->metadata, "language", NULL, 0);
+ if (entry) {
+ const char *iso6391lang = av_convert_lang_to(entry->value, AV_LANG_ISO639_1);
+ if (iso6391lang) {
+ int i;
+ for (i = 0; i < asf->nb_languages; i++) {
+ if (!strcmp(asf->languages[i], iso6391lang)) {
+ asf->streams[n].stream_language_index = i;
+ break;
+ }
+ }
+ if (i >= asf->nb_languages) {
+ asf->languages[asf->nb_languages] = iso6391lang;
+ asf->streams[n].stream_language_index = asf->nb_languages;
+ asf->nb_languages++;
+ }
+ }
+ } else {
+ asf->streams[n].stream_language_index = 128;
+ }
}
if (asf->is_streamed) {
@@ -441,13 +466,48 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
end_header(pb, hpos);
- /* unknown headers */
+ /* header_extension */
hpos = put_header(pb, &ff_asf_head1_guid);
ff_put_guid(pb, &ff_asf_head2_guid);
avio_wl16(pb, 6);
+ avio_wl32(pb, 0); /* length, to be filled later */
+ if (asf->nb_languages) {
+ int64_t hpos2;
+ int i;
+
+ hpos2 = put_header(pb, &ff_asf_language_guid);
+ avio_wl16(pb, asf->nb_languages);
+ for (i = 0; i < asf->nb_languages; i++) {
+ avio_w8(pb, 6);
+ avio_put_str16le(pb, asf->languages[i]);
+ }
+ end_header(pb, hpos2);
+
+ for (n = 0; n < s->nb_streams; n++) {
+ int64_t es_pos;
+ if (asf->streams[n].stream_language_index > 127)
+ continue;
+ es_pos = put_header(pb, &ff_asf_extended_stream_properties_object);
+ avio_wl64(pb, 0); /* start time */
+ avio_wl64(pb, 0); /* end time */
+ avio_wl32(pb, s->streams[n]->codec->bit_rate); /* data bitrate bps */
+ avio_wl32(pb, 5000); /* buffer size ms */
+ avio_wl32(pb, 0); /* initial buffer fullness */
+ avio_wl32(pb, s->streams[n]->codec->bit_rate); /* peak data bitrate */
+ avio_wl32(pb, 5000); /* maximum buffer size ms */
+ avio_wl32(pb, 0); /* max initial buffer fullness */
+ avio_wl32(pb, 0); /* max object size */
+ avio_wl32(pb, (!asf->is_streamed && pb->seekable) << 1); /* flags - seekable */
+ avio_wl16(pb, n + 1); /* stream number */
+ avio_wl16(pb, asf->streams[n].stream_language_index); /* language id index */
+ avio_wl64(pb, 0); /* avg time per frame */
+ avio_wl16(pb, 0); /* stream name count */
+ avio_wl16(pb, 0); /* payload extension system count */
+ end_header(pb, es_pos);
+ }
+ }
if (has_aspect_ratio) {
int64_t hpos2;
- avio_wl32(pb, 26 + has_aspect_ratio * 84);
hpos2 = put_header(pb, &ff_asf_metadata_header);
avio_wl16(pb, 2 * has_aspect_ratio);
for (n = 0; n < s->nb_streams; n++) {
@@ -475,8 +535,13 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
}
}
end_header(pb, hpos2);
- } else {
- avio_wl32(pb, 0);
+ }
+ {
+ int64_t pos1;
+ pos1 = avio_tell(pb);
+ avio_seek(pb, hpos + 42, SEEK_SET);
+ avio_wl32(pb, pos1 - hpos - 46);
+ avio_seek(pb, pos1, SEEK_SET);
}
end_header(pb, hpos);