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
|
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;
|
|||||||
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 @@
|
|||||||
#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 {
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
&& 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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user