summaryrefslogtreecommitdiff
path: root/contrib/ffmpeg/libavformat/asf.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ffmpeg/libavformat/asf.c')
-rw-r--r--contrib/ffmpeg/libavformat/asf.c182
1 files changed, 124 insertions, 58 deletions
diff --git a/contrib/ffmpeg/libavformat/asf.c b/contrib/ffmpeg/libavformat/asf.c
index 498f6e79e..30330c535 100644
--- a/contrib/ffmpeg/libavformat/asf.c
+++ b/contrib/ffmpeg/libavformat/asf.c
@@ -23,6 +23,9 @@
#include "mpegaudio.h"
#include "asf.h"
#include "common.h"
+#include "asfcrypt.h"
+
+extern void ff_mms_set_stream_selection(URLContext *h, AVFormatContext *format);
#undef NDEBUG
#include <assert.h>
@@ -84,7 +87,7 @@ static void print_guid(const GUID *g)
static void get_guid(ByteIOContext *s, GUID *g)
{
assert(sizeof(*g) == 16);
- get_buffer(s, g, sizeof(*g));
+ get_buffer(s, *g, sizeof(*g));
}
#if 0
@@ -119,9 +122,6 @@ static void get_str16_nolen(ByteIOContext *pb, int len, char *buf, int buf_size)
static int asf_probe(AVProbeData *pd)
{
/* check file header */
- if (pd->buf_size <= 32)
- return 0;
-
if (!memcmp(pd->buf, &asf_header, sizeof(GUID)))
return AVPROBE_SCORE_MAX;
else
@@ -142,14 +142,16 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
ASFContext *asf = s->priv_data;
GUID g;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
ASFStream *asf_st;
int size, i;
int64_t gsize;
AVRational dar[128];
+ uint32_t bitrate[128];
memset(dar, 0, sizeof(dar));
+ memset(bitrate, 0, sizeof(bitrate));
get_guid(pb, &g);
if (memcmp(&g, &asf_header, sizeof(GUID)))
@@ -197,8 +199,8 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
int type, type_specific_size, sizeX;
uint64_t total_size;
unsigned int tag1;
- int64_t pos1, pos2;
- int test_for_ext_stream_audio;
+ int64_t pos1, pos2, start_time;
+ int test_for_ext_stream_audio, is_dvr_ms_audio=0;
pos1 = url_ftell(pb);
@@ -210,10 +212,11 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
if (!asf_st)
goto fail;
st->priv_data = asf_st;
- st->start_time = asf->hdr.preroll;
+ start_time = asf->hdr.preroll;
+
if(!(asf->hdr.flags & 0x01)) { // if we aren't streaming...
st->duration = asf->hdr.send_time /
- (10000000 / 1000) - st->start_time;
+ (10000000 / 1000) - start_time;
}
get_guid(pb, &g);
@@ -244,6 +247,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_guid(pb, &g);
if (!memcmp(&g, &ext_stream_audio_stream, sizeof(GUID))) {
type = CODEC_TYPE_AUDIO;
+ is_dvr_ms_audio=1;
get_guid(pb, &g);
get_le32(pb);
get_le32(pb);
@@ -256,7 +260,13 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec->codec_type = type;
if (type == CODEC_TYPE_AUDIO) {
get_wav_header(pb, st->codec, type_specific_size);
- st->need_parsing = 1;
+ if (is_dvr_ms_audio) {
+ // codec_id and codec_tag are unreliable in dvr_ms
+ // files. Set them later by probing stream.
+ st->codec->codec_id = CODEC_ID_NONE;
+ st->codec->codec_tag = 0;
+ }
+ st->need_parsing = AVSTREAM_PARSE_FULL;
/* We have to init the frame size at some point .... */
pos2 = url_ftell(pb);
if (gsize >= (pos2 + 8 - pos1 + 24)) {
@@ -333,7 +343,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
st->codec->codec_tag = tag1;
st->codec->codec_id = codec_get_id(codec_bmp_tags, tag1);
if(tag1 == MKTAG('D', 'V', 'R', ' '))
- st->need_parsing = 1;
+ st->need_parsing = AVSTREAM_PARSE_FULL;
}
pos2 = url_ftell(pb);
url_fskip(pb, gsize - (pos2 - pos1 + 24));
@@ -363,7 +373,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
bitrate= get_le32(pb);
stream_id= (flags & 0x7f);
// av_log(NULL, AV_LOG_ERROR, "flags: 0x%x stream id %d, bitrate %d\n", flags, stream_id, bitrate);
- asf->stream_bitrates[stream_id-1]= bitrate;
+ asf->stream_bitrates[stream_id]= bitrate;
}
} else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) {
int desc_count, i;
@@ -383,12 +393,27 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
{
if (!strcmp(name,"WM/AlbumTitle")) get_str16_nolen(pb, value_len, s->album, sizeof(s->album));
else if(!strcmp(name,"WM/Genre" )) get_str16_nolen(pb, value_len, s->genre, sizeof(s->genre));
+ else if(!strcmp(name,"WM/Year" )) {
+ char year[8];
+ get_str16_nolen(pb, value_len, year, sizeof(year));
+ s->year = atoi(year);
+ }
+ else if(!strcmp(name,"WM/Track") && s->track == 0) {
+ char track[8];
+ get_str16_nolen(pb, value_len, track, sizeof(track));
+ s->track = strtol(track, NULL, 10) + 1;
+ }
+ else if(!strcmp(name,"WM/TrackNumber")) {
+ char track[8];
+ get_str16_nolen(pb, value_len, track, sizeof(track));
+ s->track = strtol(track, NULL, 10);
+ }
else url_fskip(pb, value_len);
}
if ((value_type >= 2) && (value_type <= 5)) // boolean or DWORD or QWORD or WORD
{
value_num= get_value(pb, value_type);
- if (!strcmp(name,"WM/Track" )) s->track = value_num + 1;
+ if (!strcmp(name,"WM/Track" ) && s->track == 0) s->track = value_num + 1;
if (!strcmp(name,"WM/TrackNumber")) s->track = value_num;
}
}
@@ -407,7 +432,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_str16_nolen(pb, name_len, name, sizeof(name));
//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d <%s>\n", i, stream_num, name_len, value_type, value_len, name);
- value_num= get_le16(pb);//we should use get_value() here but it doesnt work 2 is le16 here but le32 elsewhere
+ value_num= get_le16(pb);//we should use get_value() here but it does not work 2 is le16 here but le32 elsewhere
url_fskip(pb, value_len - 2);
if(stream_num<128){
@@ -417,13 +442,13 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
}
} else if (!memcmp(&g, &ext_stream_header, sizeof(GUID))) {
int ext_len, payload_ext_ct, stream_ct;
- uint32_t ext_d;
+ uint32_t ext_d, leak_rate, stream_num;
int64_t pos_ex_st;
pos_ex_st = url_ftell(pb);
get_le64(pb); // starttime
get_le64(pb); // endtime
- get_le32(pb); // leak-datarate
+ leak_rate = get_le32(pb); // leak-datarate
get_le32(pb); // bucket-datasize
get_le32(pb); // init-bucket-fullness
get_le32(pb); // alt-leak-datarate
@@ -431,12 +456,15 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_le32(pb); // alt-init-bucket-fullness
get_le32(pb); // max-object-size
get_le32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
- get_le16(pb); // stream-num
+ stream_num = get_le16(pb); // stream-num
get_le16(pb); // stream-language-id-index
get_le64(pb); // avg frametime in 100ns units
stream_ct = get_le16(pb); //stream-name-count
payload_ext_ct = get_le16(pb); //payload-extension-system-count
+ if (stream_num < 128)
+ bitrate[stream_num] = leak_rate;
+
for (i=0; i<stream_ct; i++){
get_le16(pb);
ext_len = get_le16(pb);
@@ -500,11 +528,14 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
for(i=0; i<128; i++){
int stream_num= asf->asfid2avid[i];
- if(stream_num>=0 && dar[i].num>0 && dar[i].den>0){
+ if(stream_num>=0){
AVCodecContext *codec= s->streams[stream_num]->codec;
- av_reduce(&codec->sample_aspect_ratio.num,
- &codec->sample_aspect_ratio.den,
- dar[i].num, dar[i].den, INT_MAX);
+ if (!codec->bit_rate)
+ codec->bit_rate = bitrate[i];
+ if (dar[i].num > 0 && dar[i].den > 0)
+ av_reduce(&codec->sample_aspect_ratio.num,
+ &codec->sample_aspect_ratio.den,
+ dar[i].num, dar[i].den, INT_MAX);
//av_log(NULL, AV_LOG_ERROR, "dar %d:%d sar=%d:%d\n", dar[i].num, dar[i].den, codec->sample_aspect_ratio.num, codec->sample_aspect_ratio.den);
}
}
@@ -539,12 +570,12 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
static int asf_get_packet(AVFormatContext *s)
{
ASFContext *asf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
uint32_t packet_length, padsize;
int rsize = 8;
int c, d, e, off;
- off= (url_ftell(&s->pb) - s->data_offset) % asf->packet_size + 3;
+ off= (url_ftell(s->pb) - s->data_offset) % asf->packet_size + 3;
c=d=e=-1;
while(off-- > 0){
@@ -615,7 +646,7 @@ static int asf_get_packet(AVFormatContext *s)
*/
static int asf_read_frame_header(AVFormatContext *s){
ASFContext *asf = s->priv_data;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
int rsize = 1;
int num = get_byte(pb);
int64_t ts0, ts1;
@@ -651,7 +682,7 @@ static int asf_read_frame_header(AVFormatContext *s){
url_fskip(pb, asf->packet_replic_size - 8);
rsize += asf->packet_replic_size; // FIXME - check validity
} else if (asf->packet_replic_size==1){
- // multipacket - frag_offset is begining timestamp
+ // multipacket - frag_offset is beginning timestamp
asf->packet_time_start = asf->packet_frag_offset;
asf->packet_frag_offset = 0;
asf->packet_frag_timestamp = asf->packet_timestamp;
@@ -688,11 +719,11 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
ASFContext *asf = s->priv_data;
ASFStream *asf_st = 0;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
//static int pc = 0;
for (;;) {
if(url_feof(pb))
- return AVERROR_IO;
+ return AVERROR(EIO);
if (asf->packet_size_left < FRAME_HEADER_SIZE
|| asf->packet_segments < 1) {
//asf->packet_size_left <= asf->packet_padsize) {
@@ -702,10 +733,10 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
/* fail safe */
url_fskip(pb, ret);
- asf->packet_pos= url_ftell(&s->pb);
+ asf->packet_pos= url_ftell(s->pb);
if (asf->data_object_size != (uint64_t)-1 &&
(asf->packet_pos - asf->data_object_offset >= asf->data_object_size))
- return AVERROR_IO; /* Do not exceed the size of the data object */
+ return AVERROR(EIO); /* Do not exceed the size of the data object */
ret = asf_get_packet(s);
//printf("READ ASF PACKET %d r:%d c:%d\n", ret, asf->packet_size_left, pc++);
if (ret < 0)
@@ -735,7 +766,7 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
asf_st = asf->asf_st;
if (asf->packet_replic_size == 1) {
- // frag_offset is here used as the begining timestamp
+ // frag_offset is here used as the beginning timestamp
asf->packet_frag_timestamp = asf->packet_time_start;
asf->packet_time_start += asf->packet_time_delta;
asf->packet_obj_size = asf->packet_frag_size = get_byte(pb);
@@ -751,6 +782,15 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
asf->packet_multi_size -= asf->packet_obj_size;
//printf("COMPRESS size %d %d %d ms:%d\n", asf->packet_obj_size, asf->packet_frag_timestamp, asf->packet_size_left, asf->packet_multi_size);
}
+ if( /*asf->packet_frag_size == asf->packet_obj_size*/
+ asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size
+ && asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size){
+ av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n",
+ asf_st->frag_offset, asf->packet_frag_size,
+ asf->packet_obj_size, asf_st->pkt.size);
+ asf->packet_obj_size= asf_st->pkt.size;
+ }
+
if ( asf_st->pkt.size != asf->packet_obj_size
|| asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) { //FIXME is this condition sufficient?
if(asf_st->pkt.data){
@@ -791,13 +831,29 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
get_buffer(pb, asf_st->pkt.data + asf->packet_frag_offset,
asf->packet_frag_size);
+ if (s->key && s->keylen == 20)
+ ff_asfcrypt_dec(s->key, asf_st->pkt.data + asf->packet_frag_offset,
+ asf->packet_frag_size);
asf_st->frag_offset += asf->packet_frag_size;
/* test if whole packet is read */
if (asf_st->frag_offset == asf_st->pkt.size) {
+ //workaround for macroshit radio DVR-MS files
+ if( s->streams[asf->stream_index]->codec->codec_id == CODEC_ID_MPEG2VIDEO
+ && asf_st->pkt.size > 100){
+ int i;
+ for(i=0; i<asf_st->pkt.size && !asf_st->pkt.data[i]; i++);
+ if(i == asf_st->pkt.size){
+ av_log(s, AV_LOG_DEBUG, "discarding ms fart\n");
+ asf_st->frag_offset = 0;
+ av_free_packet(&asf_st->pkt);
+ continue;
+ }
+ }
+
/* return packet */
if (asf_st->ds_span > 1) {
if(asf_st->pkt.size != asf_st->ds_packet_size * asf_st->ds_span){
- av_log(s, AV_LOG_ERROR, "pkt.size != ds_packet_size * ds_span\n");
+ av_log(s, AV_LOG_ERROR, "pkt.size != ds_packet_size * ds_span (%d %d %d)\n", asf_st->pkt.size, asf_st->ds_packet_size, asf_st->ds_span);
}else{
/* packet descrambling */
uint8_t *newdata = av_malloc(asf_st->pkt.size);
@@ -833,18 +889,6 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
return 0;
}
-static int asf_read_close(AVFormatContext *s)
-{
- int i;
-
- for(i=0;i<s->nb_streams;i++) {
- AVStream *st = s->streams[i];
- av_free(st->priv_data);
- av_free(st->codec->palctrl);
- }
- return 0;
-}
-
// Added to support seeking after packets have been read
// If information is not reset, read_packet fails due to
// leftover information from previous reads
@@ -883,6 +927,19 @@ static void asf_reset_header(AVFormatContext *s)
asf->asf_st= NULL;
}
+static int asf_read_close(AVFormatContext *s)
+{
+ int i;
+
+ asf_reset_header(s);
+ for(i=0;i<s->nb_streams;i++) {
+ AVStream *st = s->streams[i];
+ av_free(st->priv_data);
+ av_free(st->codec->palctrl);
+ }
+ return 0;
+}
+
static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit)
{
ASFContext *asf = s->priv_data;
@@ -899,7 +956,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos,
pos= (pos+asf->packet_size-1-s->data_offset)/asf->packet_size*asf->packet_size+ s->data_offset;
*ppos= pos;
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
//printf("asf_read_pts\n");
asf_reset_header(s);
@@ -943,21 +1000,21 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index)
int i;
int pct,ict;
- current_pos = url_ftell(&s->pb);
+ current_pos = url_ftell(s->pb);
- url_fseek(&s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
- get_guid(&s->pb, &g);
+ url_fseek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET);
+ get_guid(s->pb, &g);
if (!memcmp(&g, &index_guid, sizeof(GUID))) {
- gsize = get_le64(&s->pb);
- get_guid(&s->pb, &g);
- itime=get_le64(&s->pb);
- pct=get_le32(&s->pb);
- ict=get_le32(&s->pb);
+ gsize = get_le64(s->pb);
+ get_guid(s->pb, &g);
+ itime=get_le64(s->pb);
+ pct=get_le32(s->pb);
+ ict=get_le32(s->pb);
av_log(NULL, AV_LOG_DEBUG, "itime:0x%"PRIx64", pct:%d, ict:%d\n",itime,pct,ict);
for (i=0;i<ict;i++){
- int pktnum=get_le32(&s->pb);
- int pktct =get_le16(&s->pb);
+ int pktnum=get_le32(s->pb);
+ int pktct =get_le16(s->pb);
av_log(NULL, AV_LOG_DEBUG, "pktnum:%d, pktct:%d\n", pktnum, pktct);
pos=s->data_offset + asf->packet_size*(int64_t)pktnum;
@@ -967,7 +1024,7 @@ static void asf_build_simple_index(AVFormatContext *s, int stream_index)
}
asf->index_read= 1;
}
- url_fseek(&s->pb, current_pos, SEEK_SET);
+ url_fseek(s->pb, current_pos, SEEK_SET);
}
static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int flags)
@@ -980,6 +1037,15 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int
if (asf->packet_size <= 0)
return -1;
+ /* Try using the protocol's read_seek if available */
+ if(s->pb) {
+ int ret = av_url_read_fseek(s->pb, stream_index, pts, flags);
+ if(ret >= 0)
+ asf_reset_header(s);
+ if (ret != AVERROR(ENOSYS))
+ return ret;
+ }
+
if (!asf->index_read)
asf_build_simple_index(s, stream_index);
@@ -997,10 +1063,10 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int
// various attempts to find key frame have failed so far
// asf_reset_header(s);
- // url_fseek(&s->pb, pos, SEEK_SET);
+ // url_fseek(s->pb, pos, SEEK_SET);
// key_pos = pos;
// for(i=0;i<16;i++){
- // pos = url_ftell(&s->pb);
+ // pos = url_ftell(s->pb);
// if (av_read_frame(s, &pkt) < 0){
// av_log(s, AV_LOG_INFO, "seek failed\n");
// return -1;
@@ -1018,7 +1084,7 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, int64_t pts, int
/* do the seek */
av_log(NULL, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
- url_fseek(&s->pb, pos, SEEK_SET);
+ url_fseek(s->pb, pos, SEEK_SET);
}
asf_reset_header(s);
return 0;