* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+#include "libavutil/common.h"
+#include "libavcodec/mpegaudio.h"
#include "avformat.h"
#include "riff.h"
-#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>
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
{
ASFContext *asf = s->priv_data;
GUID g;
- ByteIOContext *pb = &s->pb;
+ ByteIOContext *pb = s->pb;
AVStream *st;
ASFStream *asf_st;
int size, i;
get_guid(pb, &g);
if (memcmp(&g, &asf_header, sizeof(GUID)))
- goto fail;
+ return -1;
get_le64(pb);
get_le32(pb);
get_byte(pb);
break;
}
if (gsize < 24)
- goto fail;
+ return -1;
if (!memcmp(&g, &file_header, sizeof(GUID))) {
get_guid(pb, &asf->hdr.guid);
asf->hdr.file_size = get_le64(pb);
asf->hdr.create_time = get_le64(pb);
asf->nb_packets = get_le64(pb);
- asf->hdr.send_time = get_le64(pb);
asf->hdr.play_time = get_le64(pb);
+ asf->hdr.send_time = get_le64(pb);
asf->hdr.preroll = get_le32(pb);
asf->hdr.ignore = get_le32(pb);
asf->hdr.flags = get_le32(pb);
st = av_new_stream(s, 0);
if (!st)
- goto fail;
+ return AVERROR(ENOMEM);
av_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
asf_st = av_mallocz(sizeof(ASFStream));
if (!asf_st)
- goto fail;
+ return AVERROR(ENOMEM);
st->priv_data = asf_st;
start_time = asf->hdr.preroll;
test_for_ext_stream_audio = 1;
type = CODEC_TYPE_UNKNOWN;
} else {
- goto fail;
+ return -1;
}
get_guid(pb, &g);
total_size = get_le64(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 (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/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));
}
else url_fskip(pb, value_len);
}
- if ((value_type >= 2) && (value_type <= 5)) // boolean or DWORD or QWORD or WORD
+ else if (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
+ url_fskip(pb, value_len);
}
} else if (!memcmp(&g, &metadata_header, sizeof(GUID))) {
int n, stream_num, name_len, value_len, value_type, value_num;
}
#endif
} else if (url_feof(pb)) {
- goto fail;
+ return -1;
} else {
url_fseek(pb, gsize - 24, SEEK_CUR);
}
get_byte(pb);
get_byte(pb);
if (url_feof(pb))
- goto fail;
+ return -1;
asf->data_offset = url_ftell(pb);
asf->packet_size_left = 0;
}
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) \
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){
*/
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;
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;
{
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))
/* 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(EIO); /* Do not exceed the size of the data object */
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);
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) {
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
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->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;
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);
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;
}
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)
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);
// 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;
/* 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;
AVInputFormat asf_demuxer = {
"asf",
- "asf format",
+ NULL_IF_CONFIG_SMALL("ASF format"),
sizeof(ASFContext),
asf_probe,
asf_read_header,