📄 asf.c
字号:
int j;
// av_log(NULL, AV_LOG_ERROR, "stream bitrate properties\n");
// av_log(NULL, AV_LOG_ERROR, "streams %d\n", streams);
for(j = 0; j < stream_count; j++) {
int flags, bitrate, stream_id;
flags= get_le16(pb);
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]= bitrate;
}
} else if (!memcmp(&g, &extended_content_header, sizeof(GUID))) {
int desc_count, i;
desc_count = get_le16(pb);
for(i=0;i<desc_count;i++)
{
int name_len,value_type,value_len;
uint64_t value_num = 0;
char name[1024];
name_len = get_le16(pb);
get_str16_nolen(pb, name_len, name, sizeof(name));
value_type = get_le16(pb);
value_len = get_le16(pb);
if ((value_type == 0) || (value_type == 1)) // unicode or byte
{
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/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 == 0) s->track = value_num + 1;
if (!strcmp(name,"WM/TrackNumber")) s->track = value_num;
}
}
} else if (!memcmp(&g, &metadata_header, sizeof(GUID))) {
int n, stream_num, name_len, value_len, value_type, value_num;
n = get_le16(pb);
for(i=0;i<n;i++) {
char name[1024];
get_le16(pb); //lang_list_index
stream_num= get_le16(pb);
name_len= get_le16(pb);
value_type= get_le16(pb);
value_len= get_le32(pb);
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 does not work 2 is le16 here but le32 elsewhere
url_fskip(pb, value_len - 2);
if(stream_num<128){
if (!strcmp(name, "AspectRatioX")) dar[stream_num].num= value_num;
else if(!strcmp(name, "AspectRatioY")) dar[stream_num].den= value_num;
}
}
} else if (!memcmp(&g, &ext_stream_header, sizeof(GUID))) {
int ext_len, payload_ext_ct, stream_ct;
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
leak_rate = get_le32(pb); // leak-datarate
get_le32(pb); // bucket-datasize
get_le32(pb); // init-bucket-fullness
get_le32(pb); // alt-leak-datarate
get_le32(pb); // alt-bucket-datasize
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)
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);
url_fseek(pb, ext_len, SEEK_CUR);
}
for (i=0; i<payload_ext_ct; i++){
get_guid(pb, &g);
ext_d=get_le16(pb);
ext_len=get_le32(pb);
url_fseek(pb, ext_len, SEEK_CUR);
}
// there could be a optional stream properties object to follow
// if so the next iteration will pick it up
} else if (!memcmp(&g, &head1_guid, sizeof(GUID))) {
int v1, v2;
get_guid(pb, &g);
v1 = get_le32(pb);
v2 = get_le16(pb);
#if 0
} else if (!memcmp(&g, &codec_comment_header, sizeof(GUID))) {
int len, v1, n, num;
char str[256], *q;
char tag[16];
get_guid(pb, &g);
print_guid(&g);
n = get_le32(pb);
for(i=0;i<n;i++) {
num = get_le16(pb); /* stream number */
get_str16(pb, str, sizeof(str));
get_str16(pb, str, sizeof(str));
len = get_le16(pb);
q = tag;
while (len > 0) {
v1 = get_byte(pb);
if ((q - tag) < sizeof(tag) - 1)
*q++ = v1;
len--;
}
*q = '\0';
}
#endif
} else if (url_feof(pb)) {
goto fail;
} else {
url_fseek(pb, gsize - 24, SEEK_CUR);
}
}
get_guid(pb, &g);
get_le64(pb);
get_byte(pb);
get_byte(pb);
if (url_feof(pb))
goto fail;
asf->data_offset = url_ftell(pb);
asf->packet_size_left = 0;
for(i=0; i<128; i++){
int stream_num= asf->asfid2avid[i];
if(stream_num>=0){
AVCodecContext *codec= s->streams[stream_num]->codec;
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);
}
}
return 0;
fail:
for(i=0;i<s->nb_streams;i++) {
AVStream *st = s->streams[i];
if (st) {
av_free(st->priv_data);
av_free(st->codec->extradata);
}
av_free(st);
}
return -1;
}
#define DO_2BITS(bits, var, defval) \
switch (bits & 3) \
{ \
case 3: var = get_le32(pb); rsize += 4; break; \
case 2: var = get_le16(pb); rsize += 2; break; \
case 1: var = get_byte(pb); rsize++; break; \
default: var = defval; break; \
}
/**
*
* @return <0 in case of an error
*/
static int asf_get_packet(AVFormatContext *s)
{
ASFContext *asf = s->priv_data;
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;
c=d=e=-1;
while(off-- > 0){
c=d; d=e;
e= get_byte(pb);
if(c == 0x82 && !d && !e)
break;
}
if (c != 0x82) {
if (!url_feof(pb))
av_log(s, AV_LOG_ERROR, "ff asf bad header %x at:%"PRId64"\n", c, url_ftell(pb));
}
if ((c & 0x8f) == 0x82) {
if (d || e) {
if (!url_feof(pb))
av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n");
return -1;
}
c= get_byte(pb);
d= get_byte(pb);
rsize+=3;
}else{
url_fseek(pb, -1, SEEK_CUR); //FIXME
}
asf->packet_flags = c;
asf->packet_property = d;
DO_2BITS(asf->packet_flags >> 5, packet_length, asf->packet_size);
DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored
DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length
//the following checks prevent overflows and infinite loops
if(packet_length >= (1U<<29)){
av_log(s, AV_LOG_ERROR, "invalid packet_length %d at:%"PRId64"\n", packet_length, url_ftell(pb));
return -1;
}
if(padsize >= packet_length){
av_log(s, AV_LOG_ERROR, "invalid padsize %d at:%"PRId64"\n", padsize, url_ftell(pb));
return -1;
}
asf->packet_timestamp = get_le32(pb);
get_le16(pb); /* duration */
// rsize has at least 11 bytes which have to be present
if (asf->packet_flags & 0x01) {
asf->packet_segsizetype = get_byte(pb); rsize++;
asf->packet_segments = asf->packet_segsizetype & 0x3f;
} else {
asf->packet_segments = 1;
asf->packet_segsizetype = 0x80;
}
asf->packet_size_left = packet_length - padsize - rsize;
if (packet_length < asf->hdr.min_pktsize)
padsize += asf->hdr.min_pktsize - packet_length;
asf->packet_padsize = padsize;
#ifdef DEBUG
printf("packet: size=%d padsize=%d left=%d\n", asf->packet_size, asf->packet_padsize, asf->packet_size_left);
#endif
return 0;
}
/**
*
* @return <0 if error
*/
static int asf_read_frame_header(AVFormatContext *s){
ASFContext *asf = s->priv_data;
ByteIOContext *pb = &s->pb;
int rsize = 1;
int num = get_byte(pb);
int64_t ts0, ts1;
asf->packet_segments--;
asf->packet_key_frame = num >> 7;
asf->stream_index = asf->asfid2avid[num & 0x7f];
// sequence should be ignored!
DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
//printf("key:%d stream:%d seq:%d offset:%d replic_size:%d\n", asf->packet_key_frame, asf->stream_index, asf->packet_seq, //asf->packet_frag_offset, asf->packet_replic_size);
if (asf->packet_replic_size >= 8) {
asf->packet_obj_size = get_le32(pb);
if(asf->packet_obj_size >= (1<<24) || asf->packet_obj_size <= 0){
av_log(s, AV_LOG_ERROR, "packet_obj_size invalid\n");
return -1;
}
asf->packet_frag_timestamp = get_le32(pb); // timestamp
if(asf->packet_replic_size >= 8+38+4){
// for(i=0; i<asf->packet_replic_size-8; i++)
// av_log(s, AV_LOG_DEBUG, "%02X ",get_byte(pb));
// av_log(s, AV_LOG_DEBUG, "\n");
url_fskip(pb, 10);
ts0= get_le64(pb);
ts1= get_le64(pb);
url_fskip(pb, 12);
get_le32(pb);
url_fskip(pb, asf->packet_replic_size - 8 - 38 - 4);
if(ts0!= -1) asf->packet_frag_timestamp= ts0/10000;
else asf->packet_frag_timestamp= AV_NOPTS_VALUE;
}else
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
asf->packet_time_start = asf->packet_frag_offset;
asf->packet_frag_offset = 0;
asf->packet_frag_timestamp = asf->packet_timestamp;
asf->packet_time_delta = get_byte(pb);
rsize++;
}else if(asf->packet_replic_size!=0){
av_log(s, AV_LOG_ERROR, "unexpected packet_replic_size of %d\n", asf->packet_replic_size);
return -1;
}
if (asf->packet_flags & 0x01) {
DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
if(asf->packet_frag_size > asf->packet_size_left - rsize){
av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid\n");
return -1;
}
//printf("Fragsize %d\n", asf->packet_frag_size);
} else {
asf->packet_frag_size = asf->packet_size_left - rsize;
//printf("Using rest %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize);
}
if (asf->packet_replic_size == 1) {
asf->packet_multi_size = asf->packet_frag_size;
if (asf->packet_multi_size > asf->packet_size_left)
return -1;
}
asf->packet_size_left -= rsize;
//printf("___objsize____ %d %d rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize);
return 0;
}
static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
{
ASFContext *asf = s->priv_data;
ASFStream *asf_st = 0;
ByteIOContext *pb = &s->pb;
//static int pc = 0;
for (;;) {
if(url_feof(pb))
return AVERROR(EIO);
if (asf->packet_size_left < FRAME_HEADER_SIZE
|| asf->packet_segments < 1) {
//asf->packet_size_left <= asf->packet_padsize) {
int ret = asf->packet_size_left + asf->packet_padsize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -