mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
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>
This commit is contained in:
parent
0464767301
commit
79e4293613
@ -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" },
|
||||
|
@ -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[];
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user