Commit 79e42936 authored by Marton Balint's avatar Marton Balint

lavf/asfenc: add support for storing languages

Checked compatiblity with VLC, Windows Media Player 12 and Windows Media ASF
Viewer 9 series.
Reviewed-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
Signed-off-by: 's avatarMarton Balint <cus@passwd.hu>
parent 04647673
...@@ -143,6 +143,10 @@ const ff_asf_guid ff_asf_digital_signature = { ...@@ -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 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 */ /* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */
const AVMetadataConv ff_asf_metadata_conv[] = { const AVMetadataConv ff_asf_metadata_conv[] = {
{ "WM/AlbumArtist", "album_artist" }, { "WM/AlbumArtist", "album_artist" },
......
...@@ -101,6 +101,7 @@ extern const ff_asf_guid ff_asf_language_guid; ...@@ -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_content_encryption;
extern const ff_asf_guid ff_asf_ext_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_digital_signature;
extern const ff_asf_guid ff_asf_extended_stream_properties_object;
extern const AVMetadataConv ff_asf_metadata_conv[]; extern const AVMetadataConv ff_asf_metadata_conv[];
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "libavutil/dict.h" #include "libavutil/dict.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "avformat.h" #include "avformat.h"
#include "avlanguage.h"
#include "avio_internal.h" #include "avio_internal.h"
#include "internal.h" #include "internal.h"
#include "riff.h" #include "riff.h"
...@@ -220,6 +221,8 @@ typedef struct ASFContext { ...@@ -220,6 +221,8 @@ typedef struct ASFContext {
uint32_t seqno; uint32_t seqno;
int is_streamed; int is_streamed;
ASFStream streams[128]; ///< it's max number and it's not that big ASFStream streams[128]; ///< it's max number and it's not that big
const char *languages[128];
int nb_languages;
/* non streamed additonnal info */ /* non streamed additonnal info */
uint64_t nb_packets; ///< how many packets are there in the file, invalid if broadcasting uint64_t nb_packets; ///< how many packets are there in the file, invalid if broadcasting
int64_t duration; ///< in 100ns units int64_t duration; ///< in 100ns units
...@@ -403,6 +406,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, ...@@ -403,6 +406,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
bit_rate = 0; bit_rate = 0;
for (n = 0; n < s->nb_streams; n++) { for (n = 0; n < s->nb_streams; n++) {
AVDictionaryEntry *entry;
enc = s->streams[n]->codec; enc = s->streams[n]->codec;
avpriv_set_pts_info(s->streams[n], 32, 1, 1000); /* 32 bit pts in ms */ 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, ...@@ -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.num > 0
&& enc->sample_aspect_ratio.den > 0) && enc->sample_aspect_ratio.den > 0)
has_aspect_ratio++; 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) { if (asf->is_streamed) {
...@@ -441,13 +466,48 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, ...@@ -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 */ avio_wl32(pb, bit_rate ? bit_rate : -1); /* Maximum data rate in bps */
end_header(pb, hpos); end_header(pb, hpos);
/* unknown headers */ /* header_extension */
hpos = put_header(pb, &ff_asf_head1_guid); hpos = put_header(pb, &ff_asf_head1_guid);
ff_put_guid(pb, &ff_asf_head2_guid); ff_put_guid(pb, &ff_asf_head2_guid);
avio_wl16(pb, 6); 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) { if (has_aspect_ratio) {
int64_t hpos2; int64_t hpos2;
avio_wl32(pb, 26 + has_aspect_ratio * 84);
hpos2 = put_header(pb, &ff_asf_metadata_header); hpos2 = put_header(pb, &ff_asf_metadata_header);
avio_wl16(pb, 2 * has_aspect_ratio); avio_wl16(pb, 2 * has_aspect_ratio);
for (n = 0; n < s->nb_streams; n++) { for (n = 0; n < s->nb_streams; n++) {
...@@ -475,8 +535,13 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, ...@@ -475,8 +535,13 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size,
} }
} }
end_header(pb, hpos2); 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); end_header(pb, hpos);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment