annotate ffmpeg/libavformat/asfdec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * ASF compatible demuxer
yading@11 3 * Copyright (c) 2000, 2001 Fabrice Bellard
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 //#define DEBUG
yading@11 23
yading@11 24 #include "libavutil/attributes.h"
yading@11 25 #include "libavutil/avassert.h"
yading@11 26 #include "libavutil/avstring.h"
yading@11 27 #include "libavutil/bswap.h"
yading@11 28 #include "libavutil/common.h"
yading@11 29 #include "libavutil/dict.h"
yading@11 30 #include "libavutil/mathematics.h"
yading@11 31 #include "libavutil/opt.h"
yading@11 32 #include "avformat.h"
yading@11 33 #include "avio_internal.h"
yading@11 34 #include "avlanguage.h"
yading@11 35 #include "id3v2.h"
yading@11 36 #include "internal.h"
yading@11 37 #include "riff.h"
yading@11 38 #include "asf.h"
yading@11 39 #include "asfcrypt.h"
yading@11 40
yading@11 41 typedef struct {
yading@11 42 const AVClass *class;
yading@11 43 int asfid2avid[128]; ///< conversion table from asf ID 2 AVStream ID
yading@11 44 ASFStream streams[128]; ///< it's max number and it's not that big
yading@11 45 uint32_t stream_bitrates[128]; ///< max number of streams, bitrate for each (for streaming)
yading@11 46 AVRational dar[128];
yading@11 47 char stream_languages[128][6]; ///< max number of streams, language for each (RFC1766, e.g. en-US)
yading@11 48 /* non streamed additonnal info */
yading@11 49 /* packet filling */
yading@11 50 int packet_size_left;
yading@11 51 /* only for reading */
yading@11 52 uint64_t data_offset; ///< beginning of the first data packet
yading@11 53 uint64_t data_object_offset; ///< data object offset (excl. GUID & size)
yading@11 54 uint64_t data_object_size; ///< size of the data object
yading@11 55 int index_read;
yading@11 56
yading@11 57 ASFMainHeader hdr;
yading@11 58
yading@11 59 int packet_flags;
yading@11 60 int packet_property;
yading@11 61 int packet_timestamp;
yading@11 62 int packet_segsizetype;
yading@11 63 int packet_segments;
yading@11 64 int packet_seq;
yading@11 65 int packet_replic_size;
yading@11 66 int packet_key_frame;
yading@11 67 int packet_padsize;
yading@11 68 unsigned int packet_frag_offset;
yading@11 69 unsigned int packet_frag_size;
yading@11 70 int64_t packet_frag_timestamp;
yading@11 71 int packet_multi_size;
yading@11 72 int packet_obj_size;
yading@11 73 int packet_time_delta;
yading@11 74 int packet_time_start;
yading@11 75 int64_t packet_pos;
yading@11 76
yading@11 77 int stream_index;
yading@11 78
yading@11 79 ASFStream *asf_st; ///< currently decoded stream
yading@11 80
yading@11 81 int no_resync_search;
yading@11 82 } ASFContext;
yading@11 83
yading@11 84 static const AVOption options[] = {
yading@11 85 { "no_resync_search", "Don't try to resynchronize by looking for a certain optional start code", offsetof(ASFContext, no_resync_search), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
yading@11 86 { NULL },
yading@11 87 };
yading@11 88
yading@11 89 static const AVClass asf_class = {
yading@11 90 .class_name = "asf demuxer",
yading@11 91 .item_name = av_default_item_name,
yading@11 92 .option = options,
yading@11 93 .version = LIBAVUTIL_VERSION_INT,
yading@11 94 };
yading@11 95
yading@11 96 #undef NDEBUG
yading@11 97 #include <assert.h>
yading@11 98
yading@11 99 #define ASF_MAX_STREAMS 127
yading@11 100 #define FRAME_HEADER_SIZE 16
yading@11 101 // Fix Me! FRAME_HEADER_SIZE may be different. (17 is known to be too large)
yading@11 102
yading@11 103 #ifdef DEBUG
yading@11 104 static const ff_asf_guid stream_bitrate_guid = { /* (http://get.to/sdp) */
yading@11 105 0xce, 0x75, 0xf8, 0x7b, 0x8d, 0x46, 0xd1, 0x11, 0x8d, 0x82, 0x00, 0x60, 0x97, 0xc9, 0xa2, 0xb2
yading@11 106 };
yading@11 107
yading@11 108 #define PRINT_IF_GUID(g, cmp) \
yading@11 109 if (!ff_guidcmp(g, &cmp)) \
yading@11 110 av_dlog(NULL, "(GUID: %s) ", # cmp)
yading@11 111
yading@11 112 static void print_guid(ff_asf_guid *g)
yading@11 113 {
yading@11 114 int i;
yading@11 115 PRINT_IF_GUID(g, ff_asf_header);
yading@11 116 else PRINT_IF_GUID(g, ff_asf_file_header);
yading@11 117 else PRINT_IF_GUID(g, ff_asf_stream_header);
yading@11 118 else PRINT_IF_GUID(g, ff_asf_audio_stream);
yading@11 119 else PRINT_IF_GUID(g, ff_asf_audio_conceal_none);
yading@11 120 else PRINT_IF_GUID(g, ff_asf_video_stream);
yading@11 121 else PRINT_IF_GUID(g, ff_asf_video_conceal_none);
yading@11 122 else PRINT_IF_GUID(g, ff_asf_command_stream);
yading@11 123 else PRINT_IF_GUID(g, ff_asf_comment_header);
yading@11 124 else PRINT_IF_GUID(g, ff_asf_codec_comment_header);
yading@11 125 else PRINT_IF_GUID(g, ff_asf_codec_comment1_header);
yading@11 126 else PRINT_IF_GUID(g, ff_asf_data_header);
yading@11 127 else PRINT_IF_GUID(g, ff_asf_simple_index_header);
yading@11 128 else PRINT_IF_GUID(g, ff_asf_head1_guid);
yading@11 129 else PRINT_IF_GUID(g, ff_asf_head2_guid);
yading@11 130 else PRINT_IF_GUID(g, ff_asf_my_guid);
yading@11 131 else PRINT_IF_GUID(g, ff_asf_ext_stream_header);
yading@11 132 else PRINT_IF_GUID(g, ff_asf_extended_content_header);
yading@11 133 else PRINT_IF_GUID(g, ff_asf_ext_stream_embed_stream_header);
yading@11 134 else PRINT_IF_GUID(g, ff_asf_ext_stream_audio_stream);
yading@11 135 else PRINT_IF_GUID(g, ff_asf_metadata_header);
yading@11 136 else PRINT_IF_GUID(g, ff_asf_metadata_library_header);
yading@11 137 else PRINT_IF_GUID(g, ff_asf_marker_header);
yading@11 138 else PRINT_IF_GUID(g, stream_bitrate_guid);
yading@11 139 else PRINT_IF_GUID(g, ff_asf_language_guid);
yading@11 140 else
yading@11 141 av_dlog(NULL, "(GUID: unknown) ");
yading@11 142 for (i = 0; i < 16; i++)
yading@11 143 av_dlog(NULL, " 0x%02x,", (*g)[i]);
yading@11 144 av_dlog(NULL, "}\n");
yading@11 145 }
yading@11 146 #undef PRINT_IF_GUID
yading@11 147 #else
yading@11 148 #define print_guid(g)
yading@11 149 #endif
yading@11 150
yading@11 151 static int asf_probe(AVProbeData *pd)
yading@11 152 {
yading@11 153 /* check file header */
yading@11 154 if (!ff_guidcmp(pd->buf, &ff_asf_header))
yading@11 155 return AVPROBE_SCORE_MAX;
yading@11 156 else
yading@11 157 return 0;
yading@11 158 }
yading@11 159
yading@11 160 /* size of type 2 (BOOL) is 32bit for "Extended Content Description Object"
yading@11 161 * but 16 bit for "Metadata Object" and "Metadata Library Object" */
yading@11 162 static int get_value(AVIOContext *pb, int type, int type2_size)
yading@11 163 {
yading@11 164 switch (type) {
yading@11 165 case 2:
yading@11 166 return (type2_size == 32) ? avio_rl32(pb) : avio_rl16(pb);
yading@11 167 case 3:
yading@11 168 return avio_rl32(pb);
yading@11 169 case 4:
yading@11 170 return avio_rl64(pb);
yading@11 171 case 5:
yading@11 172 return avio_rl16(pb);
yading@11 173 default:
yading@11 174 return INT_MIN;
yading@11 175 }
yading@11 176 }
yading@11 177
yading@11 178 /* MSDN claims that this should be "compatible with the ID3 frame, APIC",
yading@11 179 * but in reality this is only loosely similar */
yading@11 180 static int asf_read_picture(AVFormatContext *s, int len)
yading@11 181 {
yading@11 182 AVPacket pkt = { 0 };
yading@11 183 const CodecMime *mime = ff_id3v2_mime_tags;
yading@11 184 enum AVCodecID id = AV_CODEC_ID_NONE;
yading@11 185 char mimetype[64];
yading@11 186 uint8_t *desc = NULL;
yading@11 187 AVStream *st = NULL;
yading@11 188 int ret, type, picsize, desc_len;
yading@11 189
yading@11 190 /* type + picsize + mime + desc */
yading@11 191 if (len < 1 + 4 + 2 + 2) {
yading@11 192 av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len);
yading@11 193 return AVERROR_INVALIDDATA;
yading@11 194 }
yading@11 195
yading@11 196 /* picture type */
yading@11 197 type = avio_r8(s->pb);
yading@11 198 len--;
yading@11 199 if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) {
yading@11 200 av_log(s, AV_LOG_WARNING, "Unknown attached picture type: %d.\n", type);
yading@11 201 type = 0;
yading@11 202 }
yading@11 203
yading@11 204 /* picture data size */
yading@11 205 picsize = avio_rl32(s->pb);
yading@11 206 len -= 4;
yading@11 207
yading@11 208 /* picture MIME type */
yading@11 209 len -= avio_get_str16le(s->pb, len, mimetype, sizeof(mimetype));
yading@11 210 while (mime->id != AV_CODEC_ID_NONE) {
yading@11 211 if (!strncmp(mime->str, mimetype, sizeof(mimetype))) {
yading@11 212 id = mime->id;
yading@11 213 break;
yading@11 214 }
yading@11 215 mime++;
yading@11 216 }
yading@11 217 if (id == AV_CODEC_ID_NONE) {
yading@11 218 av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n",
yading@11 219 mimetype);
yading@11 220 return 0;
yading@11 221 }
yading@11 222
yading@11 223 if (picsize >= len) {
yading@11 224 av_log(s, AV_LOG_ERROR, "Invalid attached picture data size: %d >= %d.\n",
yading@11 225 picsize, len);
yading@11 226 return AVERROR_INVALIDDATA;
yading@11 227 }
yading@11 228
yading@11 229 /* picture description */
yading@11 230 desc_len = (len - picsize) * 2 + 1;
yading@11 231 desc = av_malloc(desc_len);
yading@11 232 if (!desc)
yading@11 233 return AVERROR(ENOMEM);
yading@11 234 len -= avio_get_str16le(s->pb, len - picsize, desc, desc_len);
yading@11 235
yading@11 236 ret = av_get_packet(s->pb, &pkt, picsize);
yading@11 237 if (ret < 0)
yading@11 238 goto fail;
yading@11 239
yading@11 240 st = avformat_new_stream(s, NULL);
yading@11 241 if (!st) {
yading@11 242 ret = AVERROR(ENOMEM);
yading@11 243 goto fail;
yading@11 244 }
yading@11 245 st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
yading@11 246 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 247 st->codec->codec_id = id;
yading@11 248 st->attached_pic = pkt;
yading@11 249 st->attached_pic.stream_index = st->index;
yading@11 250 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
yading@11 251
yading@11 252 if (*desc)
yading@11 253 av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL);
yading@11 254 else
yading@11 255 av_freep(&desc);
yading@11 256
yading@11 257 av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0);
yading@11 258
yading@11 259 return 0;
yading@11 260
yading@11 261 fail:
yading@11 262 av_freep(&desc);
yading@11 263 av_free_packet(&pkt);
yading@11 264 return ret;
yading@11 265 }
yading@11 266
yading@11 267 static void get_id3_tag(AVFormatContext *s, int len)
yading@11 268 {
yading@11 269 ID3v2ExtraMeta *id3v2_extra_meta = NULL;
yading@11 270
yading@11 271 ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
yading@11 272 if (id3v2_extra_meta)
yading@11 273 ff_id3v2_parse_apic(s, &id3v2_extra_meta);
yading@11 274 ff_id3v2_free_extra_meta(&id3v2_extra_meta);
yading@11 275 }
yading@11 276
yading@11 277 static void get_tag(AVFormatContext *s, const char *key, int type, int len, int type2_size)
yading@11 278 {
yading@11 279 char *value;
yading@11 280 int64_t off = avio_tell(s->pb);
yading@11 281 #define LEN 22
yading@11 282
yading@11 283 if ((unsigned)len >= (UINT_MAX - LEN) / 2)
yading@11 284 return;
yading@11 285
yading@11 286 value = av_malloc(2 * len + LEN);
yading@11 287 if (!value)
yading@11 288 goto finish;
yading@11 289
yading@11 290 if (type == 0) { // UTF16-LE
yading@11 291 avio_get_str16le(s->pb, len, value, 2 * len + 1);
yading@11 292 } else if (type == -1) { // ASCII
yading@11 293 avio_read(s->pb, value, len);
yading@11 294 value[len]=0;
yading@11 295 } else if (type == 1) { // byte array
yading@11 296 if (!strcmp(key, "WM/Picture")) { // handle cover art
yading@11 297 asf_read_picture(s, len);
yading@11 298 } else if (!strcmp(key, "ID3")) { // handle ID3 tag
yading@11 299 get_id3_tag(s, len);
yading@11 300 } else {
yading@11 301 av_log(s, AV_LOG_VERBOSE, "Unsupported byte array in tag %s.\n", key);
yading@11 302 }
yading@11 303 goto finish;
yading@11 304 } else if (type > 1 && type <= 5) { // boolean or DWORD or QWORD or WORD
yading@11 305 uint64_t num = get_value(s->pb, type, type2_size);
yading@11 306 snprintf(value, LEN, "%"PRIu64, num);
yading@11 307 } else if (type == 6) { // (don't) handle GUID
yading@11 308 av_log(s, AV_LOG_DEBUG, "Unsupported GUID value in tag %s.\n", key);
yading@11 309 goto finish;
yading@11 310 } else {
yading@11 311 av_log(s, AV_LOG_DEBUG,
yading@11 312 "Unsupported value type %d in tag %s.\n", type, key);
yading@11 313 goto finish;
yading@11 314 }
yading@11 315 if (*value)
yading@11 316 av_dict_set(&s->metadata, key, value, 0);
yading@11 317
yading@11 318 finish:
yading@11 319 av_freep(&value);
yading@11 320 avio_seek(s->pb, off + len, SEEK_SET);
yading@11 321 }
yading@11 322
yading@11 323 static int asf_read_file_properties(AVFormatContext *s, int64_t size)
yading@11 324 {
yading@11 325 ASFContext *asf = s->priv_data;
yading@11 326 AVIOContext *pb = s->pb;
yading@11 327
yading@11 328 ff_get_guid(pb, &asf->hdr.guid);
yading@11 329 asf->hdr.file_size = avio_rl64(pb);
yading@11 330 asf->hdr.create_time = avio_rl64(pb);
yading@11 331 avio_rl64(pb); /* number of packets */
yading@11 332 asf->hdr.play_time = avio_rl64(pb);
yading@11 333 asf->hdr.send_time = avio_rl64(pb);
yading@11 334 asf->hdr.preroll = avio_rl32(pb);
yading@11 335 asf->hdr.ignore = avio_rl32(pb);
yading@11 336 asf->hdr.flags = avio_rl32(pb);
yading@11 337 asf->hdr.min_pktsize = avio_rl32(pb);
yading@11 338 asf->hdr.max_pktsize = avio_rl32(pb);
yading@11 339 if (asf->hdr.min_pktsize >= (1U << 29))
yading@11 340 return AVERROR_INVALIDDATA;
yading@11 341 asf->hdr.max_bitrate = avio_rl32(pb);
yading@11 342 s->packet_size = asf->hdr.max_pktsize;
yading@11 343
yading@11 344 return 0;
yading@11 345 }
yading@11 346
yading@11 347 static int asf_read_stream_properties(AVFormatContext *s, int64_t size)
yading@11 348 {
yading@11 349 ASFContext *asf = s->priv_data;
yading@11 350 AVIOContext *pb = s->pb;
yading@11 351 AVStream *st;
yading@11 352 ASFStream *asf_st;
yading@11 353 ff_asf_guid g;
yading@11 354 enum AVMediaType type;
yading@11 355 int type_specific_size, sizeX;
yading@11 356 unsigned int tag1;
yading@11 357 int64_t pos1, pos2, start_time;
yading@11 358 int test_for_ext_stream_audio, is_dvr_ms_audio = 0;
yading@11 359
yading@11 360 if (s->nb_streams == ASF_MAX_STREAMS) {
yading@11 361 av_log(s, AV_LOG_ERROR, "too many streams\n");
yading@11 362 return AVERROR(EINVAL);
yading@11 363 }
yading@11 364
yading@11 365 pos1 = avio_tell(pb);
yading@11 366
yading@11 367 st = avformat_new_stream(s, NULL);
yading@11 368 if (!st)
yading@11 369 return AVERROR(ENOMEM);
yading@11 370 avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */
yading@11 371 asf_st = av_mallocz(sizeof(ASFStream));
yading@11 372 if (!asf_st)
yading@11 373 return AVERROR(ENOMEM);
yading@11 374 st->priv_data = asf_st;
yading@11 375 start_time = asf->hdr.preroll;
yading@11 376
yading@11 377 asf_st->stream_language_index = 128; // invalid stream index means no language info
yading@11 378
yading@11 379 if (!(asf->hdr.flags & 0x01)) { // if we aren't streaming...
yading@11 380 int64_t fsize = avio_size(pb);
yading@11 381 if (fsize <= 0 || (int64_t)asf->hdr.file_size <= 0 || FFABS(fsize - (int64_t)asf->hdr.file_size) < 10000)
yading@11 382 st->duration = asf->hdr.play_time /
yading@11 383 (10000000 / 1000) - start_time;
yading@11 384 }
yading@11 385 ff_get_guid(pb, &g);
yading@11 386
yading@11 387 test_for_ext_stream_audio = 0;
yading@11 388 if (!ff_guidcmp(&g, &ff_asf_audio_stream)) {
yading@11 389 type = AVMEDIA_TYPE_AUDIO;
yading@11 390 } else if (!ff_guidcmp(&g, &ff_asf_video_stream)) {
yading@11 391 type = AVMEDIA_TYPE_VIDEO;
yading@11 392 } else if (!ff_guidcmp(&g, &ff_asf_jfif_media)) {
yading@11 393 type = AVMEDIA_TYPE_VIDEO;
yading@11 394 st->codec->codec_id = AV_CODEC_ID_MJPEG;
yading@11 395 } else if (!ff_guidcmp(&g, &ff_asf_command_stream)) {
yading@11 396 type = AVMEDIA_TYPE_DATA;
yading@11 397 } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {
yading@11 398 test_for_ext_stream_audio = 1;
yading@11 399 type = AVMEDIA_TYPE_UNKNOWN;
yading@11 400 } else {
yading@11 401 return -1;
yading@11 402 }
yading@11 403 ff_get_guid(pb, &g);
yading@11 404 avio_skip(pb, 8); /* total_size */
yading@11 405 type_specific_size = avio_rl32(pb);
yading@11 406 avio_rl32(pb);
yading@11 407 st->id = avio_rl16(pb) & 0x7f; /* stream id */
yading@11 408 // mapping of asf ID to AV stream ID;
yading@11 409 asf->asfid2avid[st->id] = s->nb_streams - 1;
yading@11 410
yading@11 411 avio_rl32(pb);
yading@11 412
yading@11 413 if (test_for_ext_stream_audio) {
yading@11 414 ff_get_guid(pb, &g);
yading@11 415 if (!ff_guidcmp(&g, &ff_asf_ext_stream_audio_stream)) {
yading@11 416 type = AVMEDIA_TYPE_AUDIO;
yading@11 417 is_dvr_ms_audio = 1;
yading@11 418 ff_get_guid(pb, &g);
yading@11 419 avio_rl32(pb);
yading@11 420 avio_rl32(pb);
yading@11 421 avio_rl32(pb);
yading@11 422 ff_get_guid(pb, &g);
yading@11 423 avio_rl32(pb);
yading@11 424 }
yading@11 425 }
yading@11 426
yading@11 427 st->codec->codec_type = type;
yading@11 428 if (type == AVMEDIA_TYPE_AUDIO) {
yading@11 429 int ret = ff_get_wav_header(pb, st->codec, type_specific_size);
yading@11 430 if (ret < 0)
yading@11 431 return ret;
yading@11 432 if (is_dvr_ms_audio) {
yading@11 433 // codec_id and codec_tag are unreliable in dvr_ms
yading@11 434 // files. Set them later by probing stream.
yading@11 435 st->request_probe = 1;
yading@11 436 st->codec->codec_tag = 0;
yading@11 437 }
yading@11 438 if (st->codec->codec_id == AV_CODEC_ID_AAC)
yading@11 439 st->need_parsing = AVSTREAM_PARSE_NONE;
yading@11 440 else
yading@11 441 st->need_parsing = AVSTREAM_PARSE_FULL;
yading@11 442 /* We have to init the frame size at some point .... */
yading@11 443 pos2 = avio_tell(pb);
yading@11 444 if (size >= (pos2 + 8 - pos1 + 24)) {
yading@11 445 asf_st->ds_span = avio_r8(pb);
yading@11 446 asf_st->ds_packet_size = avio_rl16(pb);
yading@11 447 asf_st->ds_chunk_size = avio_rl16(pb);
yading@11 448 avio_rl16(pb); // ds_data_size
yading@11 449 avio_r8(pb); // ds_silence_data
yading@11 450 }
yading@11 451 if (asf_st->ds_span > 1) {
yading@11 452 if (!asf_st->ds_chunk_size ||
yading@11 453 (asf_st->ds_packet_size / asf_st->ds_chunk_size <= 1) ||
yading@11 454 asf_st->ds_packet_size % asf_st->ds_chunk_size)
yading@11 455 asf_st->ds_span = 0; // disable descrambling
yading@11 456 }
yading@11 457 } else if (type == AVMEDIA_TYPE_VIDEO &&
yading@11 458 size - (avio_tell(pb) - pos1 + 24) >= 51) {
yading@11 459 avio_rl32(pb);
yading@11 460 avio_rl32(pb);
yading@11 461 avio_r8(pb);
yading@11 462 avio_rl16(pb); /* size */
yading@11 463 sizeX = avio_rl32(pb); /* size */
yading@11 464 st->codec->width = avio_rl32(pb);
yading@11 465 st->codec->height = avio_rl32(pb);
yading@11 466 /* not available for asf */
yading@11 467 avio_rl16(pb); /* panes */
yading@11 468 st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */
yading@11 469 tag1 = avio_rl32(pb);
yading@11 470 avio_skip(pb, 20);
yading@11 471 if (sizeX > 40) {
yading@11 472 st->codec->extradata_size = ffio_limit(pb, sizeX - 40);
yading@11 473 st->codec->extradata = av_mallocz(st->codec->extradata_size +
yading@11 474 FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 475 avio_read(pb, st->codec->extradata, st->codec->extradata_size);
yading@11 476 }
yading@11 477
yading@11 478 /* Extract palette from extradata if bpp <= 8 */
yading@11 479 /* This code assumes that extradata contains only palette */
yading@11 480 /* This is true for all paletted codecs implemented in libavcodec */
yading@11 481 if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) {
yading@11 482 #if HAVE_BIGENDIAN
yading@11 483 int i;
yading@11 484 for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE) / 4; i++)
yading@11 485 asf_st->palette[i] = av_bswap32(((uint32_t *)st->codec->extradata)[i]);
yading@11 486 #else
yading@11 487 memcpy(asf_st->palette, st->codec->extradata,
yading@11 488 FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
yading@11 489 #endif
yading@11 490 asf_st->palette_changed = 1;
yading@11 491 }
yading@11 492
yading@11 493 st->codec->codec_tag = tag1;
yading@11 494 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);
yading@11 495 if (tag1 == MKTAG('D', 'V', 'R', ' ')) {
yading@11 496 st->need_parsing = AVSTREAM_PARSE_FULL;
yading@11 497 /* issue658 contains wrong w/h and MS even puts a fake seq header
yading@11 498 * with wrong w/h in extradata while a correct one is in the stream.
yading@11 499 * maximum lameness */
yading@11 500 st->codec->width =
yading@11 501 st->codec->height = 0;
yading@11 502 av_freep(&st->codec->extradata);
yading@11 503 st->codec->extradata_size = 0;
yading@11 504 }
yading@11 505 if (st->codec->codec_id == AV_CODEC_ID_H264)
yading@11 506 st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
yading@11 507 }
yading@11 508 pos2 = avio_tell(pb);
yading@11 509 avio_skip(pb, size - (pos2 - pos1 + 24));
yading@11 510
yading@11 511 return 0;
yading@11 512 }
yading@11 513
yading@11 514 static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size)
yading@11 515 {
yading@11 516 ASFContext *asf = s->priv_data;
yading@11 517 AVIOContext *pb = s->pb;
yading@11 518 ff_asf_guid g;
yading@11 519 int ext_len, payload_ext_ct, stream_ct, i;
yading@11 520 uint32_t leak_rate, stream_num;
yading@11 521 unsigned int stream_languageid_index;
yading@11 522
yading@11 523 avio_rl64(pb); // starttime
yading@11 524 avio_rl64(pb); // endtime
yading@11 525 leak_rate = avio_rl32(pb); // leak-datarate
yading@11 526 avio_rl32(pb); // bucket-datasize
yading@11 527 avio_rl32(pb); // init-bucket-fullness
yading@11 528 avio_rl32(pb); // alt-leak-datarate
yading@11 529 avio_rl32(pb); // alt-bucket-datasize
yading@11 530 avio_rl32(pb); // alt-init-bucket-fullness
yading@11 531 avio_rl32(pb); // max-object-size
yading@11 532 avio_rl32(pb); // flags (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)
yading@11 533 stream_num = avio_rl16(pb); // stream-num
yading@11 534
yading@11 535 stream_languageid_index = avio_rl16(pb); // stream-language-id-index
yading@11 536 if (stream_num < 128)
yading@11 537 asf->streams[stream_num].stream_language_index = stream_languageid_index;
yading@11 538
yading@11 539 avio_rl64(pb); // avg frametime in 100ns units
yading@11 540 stream_ct = avio_rl16(pb); // stream-name-count
yading@11 541 payload_ext_ct = avio_rl16(pb); // payload-extension-system-count
yading@11 542
yading@11 543 if (stream_num < 128) {
yading@11 544 asf->stream_bitrates[stream_num] = leak_rate;
yading@11 545 asf->streams[stream_num].payload_ext_ct = 0;
yading@11 546 }
yading@11 547
yading@11 548 for (i = 0; i < stream_ct; i++) {
yading@11 549 avio_rl16(pb);
yading@11 550 ext_len = avio_rl16(pb);
yading@11 551 avio_skip(pb, ext_len);
yading@11 552 }
yading@11 553
yading@11 554 for (i = 0; i < payload_ext_ct; i++) {
yading@11 555 int size;
yading@11 556 ff_get_guid(pb, &g);
yading@11 557 size = avio_rl16(pb);
yading@11 558 ext_len = avio_rl32(pb);
yading@11 559 avio_skip(pb, ext_len);
yading@11 560 if (stream_num < 128 && i < FF_ARRAY_ELEMS(asf->streams[stream_num].payload)) {
yading@11 561 ASFPayload *p = &asf->streams[stream_num].payload[i];
yading@11 562 p->type = g[0];
yading@11 563 p->size = size;
yading@11 564 av_log(s, AV_LOG_DEBUG, "Payload extension %x %d\n", g[0], p->size );
yading@11 565 asf->streams[stream_num].payload_ext_ct ++;
yading@11 566 }
yading@11 567 }
yading@11 568
yading@11 569 return 0;
yading@11 570 }
yading@11 571
yading@11 572 static int asf_read_content_desc(AVFormatContext *s, int64_t size)
yading@11 573 {
yading@11 574 AVIOContext *pb = s->pb;
yading@11 575 int len1, len2, len3, len4, len5;
yading@11 576
yading@11 577 len1 = avio_rl16(pb);
yading@11 578 len2 = avio_rl16(pb);
yading@11 579 len3 = avio_rl16(pb);
yading@11 580 len4 = avio_rl16(pb);
yading@11 581 len5 = avio_rl16(pb);
yading@11 582 get_tag(s, "title", 0, len1, 32);
yading@11 583 get_tag(s, "author", 0, len2, 32);
yading@11 584 get_tag(s, "copyright", 0, len3, 32);
yading@11 585 get_tag(s, "comment", 0, len4, 32);
yading@11 586 avio_skip(pb, len5);
yading@11 587
yading@11 588 return 0;
yading@11 589 }
yading@11 590
yading@11 591 static int asf_read_ext_content_desc(AVFormatContext *s, int64_t size)
yading@11 592 {
yading@11 593 AVIOContext *pb = s->pb;
yading@11 594 ASFContext *asf = s->priv_data;
yading@11 595 int desc_count, i, ret;
yading@11 596
yading@11 597 desc_count = avio_rl16(pb);
yading@11 598 for (i = 0; i < desc_count; i++) {
yading@11 599 int name_len, value_type, value_len;
yading@11 600 char name[1024];
yading@11 601
yading@11 602 name_len = avio_rl16(pb);
yading@11 603 if (name_len % 2) // must be even, broken lavf versions wrote len-1
yading@11 604 name_len += 1;
yading@11 605 if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
yading@11 606 avio_skip(pb, name_len - ret);
yading@11 607 value_type = avio_rl16(pb);
yading@11 608 value_len = avio_rl16(pb);
yading@11 609 if (!value_type && value_len % 2)
yading@11 610 value_len += 1;
yading@11 611 /* My sample has that stream set to 0 maybe that mean the container.
yading@11 612 * ASF stream count starts at 1. I am using 0 to the container value
yading@11 613 * since it's unused. */
yading@11 614 if (!strcmp(name, "AspectRatioX"))
yading@11 615 asf->dar[0].num = get_value(s->pb, value_type, 32);
yading@11 616 else if (!strcmp(name, "AspectRatioY"))
yading@11 617 asf->dar[0].den = get_value(s->pb, value_type, 32);
yading@11 618 else
yading@11 619 get_tag(s, name, value_type, value_len, 32);
yading@11 620 }
yading@11 621
yading@11 622 return 0;
yading@11 623 }
yading@11 624
yading@11 625 static int asf_read_language_list(AVFormatContext *s, int64_t size)
yading@11 626 {
yading@11 627 AVIOContext *pb = s->pb;
yading@11 628 ASFContext *asf = s->priv_data;
yading@11 629 int j, ret;
yading@11 630 int stream_count = avio_rl16(pb);
yading@11 631 for (j = 0; j < stream_count; j++) {
yading@11 632 char lang[6];
yading@11 633 unsigned int lang_len = avio_r8(pb);
yading@11 634 if ((ret = avio_get_str16le(pb, lang_len, lang,
yading@11 635 sizeof(lang))) < lang_len)
yading@11 636 avio_skip(pb, lang_len - ret);
yading@11 637 if (j < 128)
yading@11 638 av_strlcpy(asf->stream_languages[j], lang,
yading@11 639 sizeof(*asf->stream_languages));
yading@11 640 }
yading@11 641
yading@11 642 return 0;
yading@11 643 }
yading@11 644
yading@11 645 static int asf_read_metadata(AVFormatContext *s, int64_t size)
yading@11 646 {
yading@11 647 AVIOContext *pb = s->pb;
yading@11 648 ASFContext *asf = s->priv_data;
yading@11 649 int n, stream_num, name_len, value_len;
yading@11 650 int ret, i;
yading@11 651 n = avio_rl16(pb);
yading@11 652
yading@11 653 for (i = 0; i < n; i++) {
yading@11 654 char name[1024];
yading@11 655 int value_type;
yading@11 656
yading@11 657 avio_rl16(pb); // lang_list_index
yading@11 658 stream_num = avio_rl16(pb);
yading@11 659 name_len = avio_rl16(pb);
yading@11 660 value_type = avio_rl16(pb); /* value_type */
yading@11 661 value_len = avio_rl32(pb);
yading@11 662
yading@11 663 if ((ret = avio_get_str16le(pb, name_len, name, sizeof(name))) < name_len)
yading@11 664 avio_skip(pb, name_len - ret);
yading@11 665 av_dlog(s, "%d stream %d name_len %2d type %d len %4d <%s>\n",
yading@11 666 i, stream_num, name_len, value_type, value_len, name);
yading@11 667
yading@11 668 if (!strcmp(name, "AspectRatioX")){
yading@11 669 int aspect_x = get_value(s->pb, value_type, 16);
yading@11 670 if(stream_num < 128)
yading@11 671 asf->dar[stream_num].num = aspect_x;
yading@11 672 } else if(!strcmp(name, "AspectRatioY")){
yading@11 673 int aspect_y = get_value(s->pb, value_type, 16);
yading@11 674 if(stream_num < 128)
yading@11 675 asf->dar[stream_num].den = aspect_y;
yading@11 676 } else {
yading@11 677 get_tag(s, name, value_type, value_len, 16);
yading@11 678 }
yading@11 679 }
yading@11 680
yading@11 681 return 0;
yading@11 682 }
yading@11 683
yading@11 684 static int asf_read_marker(AVFormatContext *s, int64_t size)
yading@11 685 {
yading@11 686 AVIOContext *pb = s->pb;
yading@11 687 int i, count, name_len, ret;
yading@11 688 char name[1024];
yading@11 689
yading@11 690 avio_rl64(pb); // reserved 16 bytes
yading@11 691 avio_rl64(pb); // ...
yading@11 692 count = avio_rl32(pb); // markers count
yading@11 693 avio_rl16(pb); // reserved 2 bytes
yading@11 694 name_len = avio_rl16(pb); // name length
yading@11 695 for (i = 0; i < name_len; i++)
yading@11 696 avio_r8(pb); // skip the name
yading@11 697
yading@11 698 for (i = 0; i < count; i++) {
yading@11 699 int64_t pres_time;
yading@11 700 int name_len;
yading@11 701
yading@11 702 avio_rl64(pb); // offset, 8 bytes
yading@11 703 pres_time = avio_rl64(pb); // presentation time
yading@11 704 avio_rl16(pb); // entry length
yading@11 705 avio_rl32(pb); // send time
yading@11 706 avio_rl32(pb); // flags
yading@11 707 name_len = avio_rl32(pb); // name length
yading@11 708 if ((ret = avio_get_str16le(pb, name_len * 2, name,
yading@11 709 sizeof(name))) < name_len)
yading@11 710 avio_skip(pb, name_len - ret);
yading@11 711 avpriv_new_chapter(s, i, (AVRational) { 1, 10000000 }, pres_time,
yading@11 712 AV_NOPTS_VALUE, name);
yading@11 713 }
yading@11 714
yading@11 715 return 0;
yading@11 716 }
yading@11 717
yading@11 718 static int asf_read_header(AVFormatContext *s)
yading@11 719 {
yading@11 720 ASFContext *asf = s->priv_data;
yading@11 721 ff_asf_guid g;
yading@11 722 AVIOContext *pb = s->pb;
yading@11 723 int i;
yading@11 724 int64_t gsize;
yading@11 725
yading@11 726 ff_get_guid(pb, &g);
yading@11 727 if (ff_guidcmp(&g, &ff_asf_header))
yading@11 728 return AVERROR_INVALIDDATA;
yading@11 729 avio_rl64(pb);
yading@11 730 avio_rl32(pb);
yading@11 731 avio_r8(pb);
yading@11 732 avio_r8(pb);
yading@11 733 memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
yading@11 734 for (;;) {
yading@11 735 uint64_t gpos = avio_tell(pb);
yading@11 736 ff_get_guid(pb, &g);
yading@11 737 gsize = avio_rl64(pb);
yading@11 738 print_guid(&g);
yading@11 739 if (!ff_guidcmp(&g, &ff_asf_data_header)) {
yading@11 740 asf->data_object_offset = avio_tell(pb);
yading@11 741 /* If not streaming, gsize is not unlimited (how?),
yading@11 742 * and there is enough space in the file.. */
yading@11 743 if (!(asf->hdr.flags & 0x01) && gsize >= 100)
yading@11 744 asf->data_object_size = gsize - 24;
yading@11 745 else
yading@11 746 asf->data_object_size = (uint64_t)-1;
yading@11 747 break;
yading@11 748 }
yading@11 749 if (gsize < 24)
yading@11 750 return AVERROR_INVALIDDATA;
yading@11 751 if (!ff_guidcmp(&g, &ff_asf_file_header)) {
yading@11 752 int ret = asf_read_file_properties(s, gsize);
yading@11 753 if (ret < 0)
yading@11 754 return ret;
yading@11 755 } else if (!ff_guidcmp(&g, &ff_asf_stream_header)) {
yading@11 756 asf_read_stream_properties(s, gsize);
yading@11 757 } else if (!ff_guidcmp(&g, &ff_asf_comment_header)) {
yading@11 758 asf_read_content_desc(s, gsize);
yading@11 759 } else if (!ff_guidcmp(&g, &ff_asf_language_guid)) {
yading@11 760 asf_read_language_list(s, gsize);
yading@11 761 } else if (!ff_guidcmp(&g, &ff_asf_extended_content_header)) {
yading@11 762 asf_read_ext_content_desc(s, gsize);
yading@11 763 } else if (!ff_guidcmp(&g, &ff_asf_metadata_header)) {
yading@11 764 asf_read_metadata(s, gsize);
yading@11 765 } else if (!ff_guidcmp(&g, &ff_asf_metadata_library_header)) {
yading@11 766 asf_read_metadata(s, gsize);
yading@11 767 } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_header)) {
yading@11 768 asf_read_ext_stream_properties(s, gsize);
yading@11 769
yading@11 770 // there could be a optional stream properties object to follow
yading@11 771 // if so the next iteration will pick it up
yading@11 772 continue;
yading@11 773 } else if (!ff_guidcmp(&g, &ff_asf_head1_guid)) {
yading@11 774 ff_get_guid(pb, &g);
yading@11 775 avio_skip(pb, 6);
yading@11 776 continue;
yading@11 777 } else if (!ff_guidcmp(&g, &ff_asf_marker_header)) {
yading@11 778 asf_read_marker(s, gsize);
yading@11 779 } else if (url_feof(pb)) {
yading@11 780 return AVERROR_EOF;
yading@11 781 } else {
yading@11 782 if (!s->keylen) {
yading@11 783 if (!ff_guidcmp(&g, &ff_asf_content_encryption)) {
yading@11 784 unsigned int len;
yading@11 785 AVPacket pkt;
yading@11 786 av_log(s, AV_LOG_WARNING,
yading@11 787 "DRM protected stream detected, decoding will likely fail!\n");
yading@11 788 len= avio_rl32(pb);
yading@11 789 av_log(s, AV_LOG_DEBUG, "Secret data:\n");
yading@11 790 av_get_packet(pb, &pkt, len); av_hex_dump_log(s, AV_LOG_DEBUG, pkt.data, pkt.size); av_free_packet(&pkt);
yading@11 791 len= avio_rl32(pb);
yading@11 792 get_tag(s, "ASF_Protection_Type", -1, len, 32);
yading@11 793 len= avio_rl32(pb);
yading@11 794 get_tag(s, "ASF_Key_ID", -1, len, 32);
yading@11 795 len= avio_rl32(pb);
yading@11 796 get_tag(s, "ASF_License_URL", -1, len, 32);
yading@11 797 } else if (!ff_guidcmp(&g, &ff_asf_ext_content_encryption)) {
yading@11 798 av_log(s, AV_LOG_WARNING,
yading@11 799 "Ext DRM protected stream detected, decoding will likely fail!\n");
yading@11 800 av_dict_set(&s->metadata, "encryption", "ASF Extended Content Encryption", 0);
yading@11 801 } else if (!ff_guidcmp(&g, &ff_asf_digital_signature)) {
yading@11 802 av_log(s, AV_LOG_INFO, "Digital signature detected!\n");
yading@11 803 }
yading@11 804 }
yading@11 805 }
yading@11 806 if (avio_tell(pb) != gpos + gsize)
yading@11 807 av_log(s, AV_LOG_DEBUG,
yading@11 808 "gpos mismatch our pos=%"PRIu64", end=%"PRId64"\n",
yading@11 809 avio_tell(pb) - gpos, gsize);
yading@11 810 avio_seek(pb, gpos + gsize, SEEK_SET);
yading@11 811 }
yading@11 812 ff_get_guid(pb, &g);
yading@11 813 avio_rl64(pb);
yading@11 814 avio_r8(pb);
yading@11 815 avio_r8(pb);
yading@11 816 if (url_feof(pb))
yading@11 817 return AVERROR_EOF;
yading@11 818 asf->data_offset = avio_tell(pb);
yading@11 819 asf->packet_size_left = 0;
yading@11 820
yading@11 821 for (i = 0; i < 128; i++) {
yading@11 822 int stream_num = asf->asfid2avid[i];
yading@11 823 if (stream_num >= 0) {
yading@11 824 AVStream *st = s->streams[stream_num];
yading@11 825 if (!st->codec->bit_rate)
yading@11 826 st->codec->bit_rate = asf->stream_bitrates[i];
yading@11 827 if (asf->dar[i].num > 0 && asf->dar[i].den > 0) {
yading@11 828 av_reduce(&st->sample_aspect_ratio.num,
yading@11 829 &st->sample_aspect_ratio.den,
yading@11 830 asf->dar[i].num, asf->dar[i].den, INT_MAX);
yading@11 831 } else if ((asf->dar[0].num > 0) && (asf->dar[0].den > 0) &&
yading@11 832 // Use ASF container value if the stream doesn't set AR.
yading@11 833 (st->codec->codec_type == AVMEDIA_TYPE_VIDEO))
yading@11 834 av_reduce(&st->sample_aspect_ratio.num,
yading@11 835 &st->sample_aspect_ratio.den,
yading@11 836 asf->dar[0].num, asf->dar[0].den, INT_MAX);
yading@11 837
yading@11 838 av_dlog(s, "i=%d, st->codec->codec_type:%d, asf->dar %d:%d sar=%d:%d\n",
yading@11 839 i, st->codec->codec_type, asf->dar[i].num, asf->dar[i].den,
yading@11 840 st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
yading@11 841
yading@11 842 // copy and convert language codes to the frontend
yading@11 843 if (asf->streams[i].stream_language_index < 128) {
yading@11 844 const char *rfc1766 = asf->stream_languages[asf->streams[i].stream_language_index];
yading@11 845 if (rfc1766 && strlen(rfc1766) > 1) {
yading@11 846 const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any
yading@11 847 const char *iso6392 = av_convert_lang_to(primary_tag,
yading@11 848 AV_LANG_ISO639_2_BIBL);
yading@11 849 if (iso6392)
yading@11 850 av_dict_set(&st->metadata, "language", iso6392, 0);
yading@11 851 }
yading@11 852 }
yading@11 853 }
yading@11 854 }
yading@11 855
yading@11 856 ff_metadata_conv(&s->metadata, NULL, ff_asf_metadata_conv);
yading@11 857
yading@11 858 return 0;
yading@11 859 }
yading@11 860
yading@11 861 #define DO_2BITS(bits, var, defval) \
yading@11 862 switch (bits & 3) { \
yading@11 863 case 3: \
yading@11 864 var = avio_rl32(pb); \
yading@11 865 rsize += 4; \
yading@11 866 break; \
yading@11 867 case 2: \
yading@11 868 var = avio_rl16(pb); \
yading@11 869 rsize += 2; \
yading@11 870 break; \
yading@11 871 case 1: \
yading@11 872 var = avio_r8(pb); \
yading@11 873 rsize++; \
yading@11 874 break; \
yading@11 875 default: \
yading@11 876 var = defval; \
yading@11 877 break; \
yading@11 878 }
yading@11 879
yading@11 880 /**
yading@11 881 * Load a single ASF packet into the demuxer.
yading@11 882 * @param s demux context
yading@11 883 * @param pb context to read data from
yading@11 884 * @return 0 on success, <0 on error
yading@11 885 */
yading@11 886 static int ff_asf_get_packet(AVFormatContext *s, AVIOContext *pb)
yading@11 887 {
yading@11 888 ASFContext *asf = s->priv_data;
yading@11 889 uint32_t packet_length, padsize;
yading@11 890 int rsize = 8;
yading@11 891 int c, d, e, off;
yading@11 892
yading@11 893 // if we do not know packet size, allow skipping up to 32 kB
yading@11 894 off = 32768;
yading@11 895 if (asf->no_resync_search)
yading@11 896 off = 3;
yading@11 897 else if (s->packet_size > 0)
yading@11 898 off = (avio_tell(pb) - s->data_offset) % s->packet_size + 3;
yading@11 899
yading@11 900 c = d = e = -1;
yading@11 901 while (off-- > 0) {
yading@11 902 c = d;
yading@11 903 d = e;
yading@11 904 e = avio_r8(pb);
yading@11 905 if (c == 0x82 && !d && !e)
yading@11 906 break;
yading@11 907 }
yading@11 908
yading@11 909 if (c != 0x82) {
yading@11 910 /* This code allows handling of -EAGAIN at packet boundaries (i.e.
yading@11 911 * if the packet sync code above triggers -EAGAIN). This does not
yading@11 912 * imply complete -EAGAIN handling support at random positions in
yading@11 913 * the stream. */
yading@11 914 if (pb->error == AVERROR(EAGAIN))
yading@11 915 return AVERROR(EAGAIN);
yading@11 916 if (!url_feof(pb))
yading@11 917 av_log(s, AV_LOG_ERROR,
yading@11 918 "ff asf bad header %x at:%"PRId64"\n", c, avio_tell(pb));
yading@11 919 }
yading@11 920 if ((c & 0x8f) == 0x82) {
yading@11 921 if (d || e) {
yading@11 922 if (!url_feof(pb))
yading@11 923 av_log(s, AV_LOG_ERROR, "ff asf bad non zero\n");
yading@11 924 return AVERROR_INVALIDDATA;
yading@11 925 }
yading@11 926 c = avio_r8(pb);
yading@11 927 d = avio_r8(pb);
yading@11 928 rsize += 3;
yading@11 929 } else if(!url_feof(pb)) {
yading@11 930 avio_seek(pb, -1, SEEK_CUR); // FIXME
yading@11 931 }
yading@11 932
yading@11 933 asf->packet_flags = c;
yading@11 934 asf->packet_property = d;
yading@11 935
yading@11 936 DO_2BITS(asf->packet_flags >> 5, packet_length, s->packet_size);
yading@11 937 DO_2BITS(asf->packet_flags >> 1, padsize, 0); // sequence ignored
yading@11 938 DO_2BITS(asf->packet_flags >> 3, padsize, 0); // padding length
yading@11 939
yading@11 940 // the following checks prevent overflows and infinite loops
yading@11 941 if (!packet_length || packet_length >= (1U << 29)) {
yading@11 942 av_log(s, AV_LOG_ERROR,
yading@11 943 "invalid packet_length %d at:%"PRId64"\n",
yading@11 944 packet_length, avio_tell(pb));
yading@11 945 return AVERROR_INVALIDDATA;
yading@11 946 }
yading@11 947 if (padsize >= packet_length) {
yading@11 948 av_log(s, AV_LOG_ERROR,
yading@11 949 "invalid padsize %d at:%"PRId64"\n", padsize, avio_tell(pb));
yading@11 950 return AVERROR_INVALIDDATA;
yading@11 951 }
yading@11 952
yading@11 953 asf->packet_timestamp = avio_rl32(pb);
yading@11 954 avio_rl16(pb); /* duration */
yading@11 955 // rsize has at least 11 bytes which have to be present
yading@11 956
yading@11 957 if (asf->packet_flags & 0x01) {
yading@11 958 asf->packet_segsizetype = avio_r8(pb);
yading@11 959 rsize++;
yading@11 960 asf->packet_segments = asf->packet_segsizetype & 0x3f;
yading@11 961 } else {
yading@11 962 asf->packet_segments = 1;
yading@11 963 asf->packet_segsizetype = 0x80;
yading@11 964 }
yading@11 965 if (rsize > packet_length - padsize) {
yading@11 966 asf->packet_size_left = 0;
yading@11 967 av_log(s, AV_LOG_ERROR,
yading@11 968 "invalid packet header length %d for pktlen %d-%d at %"PRId64"\n",
yading@11 969 rsize, packet_length, padsize, avio_tell(pb));
yading@11 970 return AVERROR_INVALIDDATA;
yading@11 971 }
yading@11 972 asf->packet_size_left = packet_length - padsize - rsize;
yading@11 973 if (packet_length < asf->hdr.min_pktsize)
yading@11 974 padsize += asf->hdr.min_pktsize - packet_length;
yading@11 975 asf->packet_padsize = padsize;
yading@11 976 av_dlog(s, "packet: size=%d padsize=%d left=%d\n",
yading@11 977 s->packet_size, asf->packet_padsize, asf->packet_size_left);
yading@11 978 return 0;
yading@11 979 }
yading@11 980
yading@11 981 /**
yading@11 982 *
yading@11 983 * @return <0 if error
yading@11 984 */
yading@11 985 static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb)
yading@11 986 {
yading@11 987 ASFContext *asf = s->priv_data;
yading@11 988 ASFStream *asfst;
yading@11 989 int rsize = 1;
yading@11 990 int num = avio_r8(pb);
yading@11 991 int i;
yading@11 992 int64_t ts0, ts1 av_unused;
yading@11 993
yading@11 994 asf->packet_segments--;
yading@11 995 asf->packet_key_frame = num >> 7;
yading@11 996 asf->stream_index = asf->asfid2avid[num & 0x7f];
yading@11 997 asfst = &asf->streams[num & 0x7f];
yading@11 998 // sequence should be ignored!
yading@11 999 DO_2BITS(asf->packet_property >> 4, asf->packet_seq, 0);
yading@11 1000 DO_2BITS(asf->packet_property >> 2, asf->packet_frag_offset, 0);
yading@11 1001 DO_2BITS(asf->packet_property, asf->packet_replic_size, 0);
yading@11 1002 av_dlog(asf, "key:%d stream:%d seq:%d offset:%d replic_size:%d\n",
yading@11 1003 asf->packet_key_frame, asf->stream_index, asf->packet_seq,
yading@11 1004 asf->packet_frag_offset, asf->packet_replic_size);
yading@11 1005 if (rsize+(int64_t)asf->packet_replic_size > asf->packet_size_left) {
yading@11 1006 av_log(s, AV_LOG_ERROR, "packet_replic_size %d is invalid\n", asf->packet_replic_size);
yading@11 1007 return AVERROR_INVALIDDATA;
yading@11 1008 }
yading@11 1009 if (asf->packet_replic_size >= 8) {
yading@11 1010 int64_t end = avio_tell(pb) + asf->packet_replic_size;
yading@11 1011 AVRational aspect;
yading@11 1012 asf->packet_obj_size = avio_rl32(pb);
yading@11 1013 if (asf->packet_obj_size >= (1 << 24) || asf->packet_obj_size <= 0) {
yading@11 1014 av_log(s, AV_LOG_ERROR, "packet_obj_size invalid\n");
yading@11 1015 asf->packet_obj_size = 0;
yading@11 1016 return AVERROR_INVALIDDATA;
yading@11 1017 }
yading@11 1018 asf->packet_frag_timestamp = avio_rl32(pb); // timestamp
yading@11 1019
yading@11 1020 for (i = 0; i < asfst->payload_ext_ct; i++) {
yading@11 1021 ASFPayload *p = &asfst->payload[i];
yading@11 1022 int size = p->size;
yading@11 1023 int64_t payend;
yading@11 1024 if (size == 0xFFFF)
yading@11 1025 size = avio_rl16(pb);
yading@11 1026 payend = avio_tell(pb) + size;
yading@11 1027 if (payend > end) {
yading@11 1028 av_log(s, AV_LOG_ERROR, "too long payload\n");
yading@11 1029 break;
yading@11 1030 }
yading@11 1031 switch (p->type) {
yading@11 1032 case 0x50:
yading@11 1033 // duration = avio_rl16(pb);
yading@11 1034 break;
yading@11 1035 case 0x54:
yading@11 1036 aspect.num = avio_r8(pb);
yading@11 1037 aspect.den = avio_r8(pb);
yading@11 1038 if (aspect.num > 0 && aspect.den > 0 && asf->stream_index >= 0) {
yading@11 1039 s->streams[asf->stream_index]->sample_aspect_ratio = aspect;
yading@11 1040 }
yading@11 1041 break;
yading@11 1042 case 0x2A:
yading@11 1043 avio_skip(pb, 8);
yading@11 1044 ts0 = avio_rl64(pb);
yading@11 1045 ts1 = avio_rl64(pb);
yading@11 1046 if (ts0!= -1) asf->packet_frag_timestamp = ts0/10000;
yading@11 1047 else asf->packet_frag_timestamp = AV_NOPTS_VALUE;
yading@11 1048 break;
yading@11 1049 case 0x5B:
yading@11 1050 case 0xB7:
yading@11 1051 case 0xCC:
yading@11 1052 case 0xC0:
yading@11 1053 case 0xA0:
yading@11 1054 //unknown
yading@11 1055 break;
yading@11 1056 }
yading@11 1057 avio_seek(pb, payend, SEEK_SET);
yading@11 1058 }
yading@11 1059
yading@11 1060 avio_seek(pb, end, SEEK_SET);
yading@11 1061 rsize += asf->packet_replic_size; // FIXME - check validity
yading@11 1062 } else if (asf->packet_replic_size == 1) {
yading@11 1063 // multipacket - frag_offset is beginning timestamp
yading@11 1064 asf->packet_time_start = asf->packet_frag_offset;
yading@11 1065 asf->packet_frag_offset = 0;
yading@11 1066 asf->packet_frag_timestamp = asf->packet_timestamp;
yading@11 1067
yading@11 1068 asf->packet_time_delta = avio_r8(pb);
yading@11 1069 rsize++;
yading@11 1070 } else if (asf->packet_replic_size != 0) {
yading@11 1071 av_log(s, AV_LOG_ERROR, "unexpected packet_replic_size of %d\n",
yading@11 1072 asf->packet_replic_size);
yading@11 1073 return AVERROR_INVALIDDATA;
yading@11 1074 }
yading@11 1075 if (asf->packet_flags & 0x01) {
yading@11 1076 DO_2BITS(asf->packet_segsizetype >> 6, asf->packet_frag_size, 0); // 0 is illegal
yading@11 1077 if (rsize > asf->packet_size_left) {
yading@11 1078 av_log(s, AV_LOG_ERROR, "packet_replic_size is invalid\n");
yading@11 1079 return AVERROR_INVALIDDATA;
yading@11 1080 } else if (asf->packet_frag_size > asf->packet_size_left - rsize) {
yading@11 1081 if (asf->packet_frag_size > asf->packet_size_left - rsize + asf->packet_padsize) {
yading@11 1082 av_log(s, AV_LOG_ERROR, "packet_frag_size is invalid (%d-%d)\n",
yading@11 1083 asf->packet_size_left, rsize);
yading@11 1084 return AVERROR_INVALIDDATA;
yading@11 1085 } else {
yading@11 1086 int diff = asf->packet_frag_size - (asf->packet_size_left - rsize);
yading@11 1087 asf->packet_size_left += diff;
yading@11 1088 asf->packet_padsize -= diff;
yading@11 1089 }
yading@11 1090 }
yading@11 1091 } else {
yading@11 1092 asf->packet_frag_size = asf->packet_size_left - rsize;
yading@11 1093 }
yading@11 1094 if (asf->packet_replic_size == 1) {
yading@11 1095 asf->packet_multi_size = asf->packet_frag_size;
yading@11 1096 if (asf->packet_multi_size > asf->packet_size_left)
yading@11 1097 return AVERROR_INVALIDDATA;
yading@11 1098 }
yading@11 1099 asf->packet_size_left -= rsize;
yading@11 1100
yading@11 1101 return 0;
yading@11 1102 }
yading@11 1103
yading@11 1104 /**
yading@11 1105 * Parse data from individual ASF packets (which were previously loaded
yading@11 1106 * with asf_get_packet()).
yading@11 1107 * @param s demux context
yading@11 1108 * @param pb context to read data from
yading@11 1109 * @param pkt pointer to store packet data into
yading@11 1110 * @return 0 if data was stored in pkt, <0 on error or 1 if more ASF
yading@11 1111 * packets need to be loaded (through asf_get_packet())
yading@11 1112 */
yading@11 1113 static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt)
yading@11 1114 {
yading@11 1115 ASFContext *asf = s->priv_data;
yading@11 1116 ASFStream *asf_st = 0;
yading@11 1117 for (;;) {
yading@11 1118 int ret;
yading@11 1119 if (url_feof(pb))
yading@11 1120 return AVERROR_EOF;
yading@11 1121
yading@11 1122 if (asf->packet_size_left < FRAME_HEADER_SIZE ||
yading@11 1123 asf->packet_segments < 1) {
yading@11 1124 int ret = asf->packet_size_left + asf->packet_padsize;
yading@11 1125
yading@11 1126 assert(ret >= 0);
yading@11 1127 /* fail safe */
yading@11 1128 avio_skip(pb, ret);
yading@11 1129
yading@11 1130 asf->packet_pos = avio_tell(pb);
yading@11 1131 if (asf->data_object_size != (uint64_t)-1 &&
yading@11 1132 (asf->packet_pos - asf->data_object_offset >= asf->data_object_size))
yading@11 1133 return AVERROR_EOF; /* Do not exceed the size of the data object */
yading@11 1134 return 1;
yading@11 1135 }
yading@11 1136 if (asf->packet_time_start == 0) {
yading@11 1137 if (asf_read_frame_header(s, pb) < 0) {
yading@11 1138 asf->packet_segments = 0;
yading@11 1139 continue;
yading@11 1140 }
yading@11 1141 if (asf->stream_index < 0 ||
yading@11 1142 s->streams[asf->stream_index]->discard >= AVDISCARD_ALL ||
yading@11 1143 (!asf->packet_key_frame &&
yading@11 1144 s->streams[asf->stream_index]->discard >= AVDISCARD_NONKEY)) {
yading@11 1145 asf->packet_time_start = 0;
yading@11 1146 /* unhandled packet (should not happen) */
yading@11 1147 avio_skip(pb, asf->packet_frag_size);
yading@11 1148 asf->packet_size_left -= asf->packet_frag_size;
yading@11 1149 if (asf->stream_index < 0)
yading@11 1150 av_log(s, AV_LOG_ERROR, "ff asf skip %d (unknown stream)\n",
yading@11 1151 asf->packet_frag_size);
yading@11 1152 continue;
yading@11 1153 }
yading@11 1154 asf->asf_st = s->streams[asf->stream_index]->priv_data;
yading@11 1155 }
yading@11 1156 asf_st = asf->asf_st;
yading@11 1157 av_assert0(asf_st);
yading@11 1158
yading@11 1159 if (asf->packet_replic_size == 1) {
yading@11 1160 // frag_offset is here used as the beginning timestamp
yading@11 1161 asf->packet_frag_timestamp = asf->packet_time_start;
yading@11 1162 asf->packet_time_start += asf->packet_time_delta;
yading@11 1163 asf->packet_obj_size = asf->packet_frag_size = avio_r8(pb);
yading@11 1164 asf->packet_size_left--;
yading@11 1165 asf->packet_multi_size--;
yading@11 1166 if (asf->packet_multi_size < asf->packet_obj_size) {
yading@11 1167 asf->packet_time_start = 0;
yading@11 1168 avio_skip(pb, asf->packet_multi_size);
yading@11 1169 asf->packet_size_left -= asf->packet_multi_size;
yading@11 1170 continue;
yading@11 1171 }
yading@11 1172 asf->packet_multi_size -= asf->packet_obj_size;
yading@11 1173 }
yading@11 1174 if (asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size &&
yading@11 1175 asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size) {
yading@11 1176 av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n",
yading@11 1177 asf_st->frag_offset, asf->packet_frag_size,
yading@11 1178 asf->packet_obj_size, asf_st->pkt.size);
yading@11 1179 asf->packet_obj_size = asf_st->pkt.size;
yading@11 1180 }
yading@11 1181
yading@11 1182 if (asf_st->pkt.size != asf->packet_obj_size ||
yading@11 1183 // FIXME is this condition sufficient?
yading@11 1184 asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) {
yading@11 1185 if (asf_st->pkt.data) {
yading@11 1186 av_log(s, AV_LOG_INFO,
yading@11 1187 "freeing incomplete packet size %d, new %d\n",
yading@11 1188 asf_st->pkt.size, asf->packet_obj_size);
yading@11 1189 asf_st->frag_offset = 0;
yading@11 1190 av_free_packet(&asf_st->pkt);
yading@11 1191 }
yading@11 1192 /* new packet */
yading@11 1193 av_new_packet(&asf_st->pkt, asf->packet_obj_size);
yading@11 1194 asf_st->seq = asf->packet_seq;
yading@11 1195 asf_st->pkt.dts = asf->packet_frag_timestamp - asf->hdr.preroll;
yading@11 1196 asf_st->pkt.stream_index = asf->stream_index;
yading@11 1197 asf_st->pkt.pos = asf_st->packet_pos = asf->packet_pos;
yading@11 1198
yading@11 1199 if (asf_st->pkt.data && asf_st->palette_changed) {
yading@11 1200 uint8_t *pal;
yading@11 1201 pal = av_packet_new_side_data(&asf_st->pkt, AV_PKT_DATA_PALETTE,
yading@11 1202 AVPALETTE_SIZE);
yading@11 1203 if (!pal) {
yading@11 1204 av_log(s, AV_LOG_ERROR, "Cannot append palette to packet\n");
yading@11 1205 } else {
yading@11 1206 memcpy(pal, asf_st->palette, AVPALETTE_SIZE);
yading@11 1207 asf_st->palette_changed = 0;
yading@11 1208 }
yading@11 1209 }
yading@11 1210 av_dlog(asf, "new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
yading@11 1211 asf->stream_index, asf->packet_key_frame,
yading@11 1212 asf_st->pkt.flags & AV_PKT_FLAG_KEY,
yading@11 1213 s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO,
yading@11 1214 asf->packet_obj_size);
yading@11 1215 if (s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
yading@11 1216 asf->packet_key_frame = 1;
yading@11 1217 if (asf->packet_key_frame)
yading@11 1218 asf_st->pkt.flags |= AV_PKT_FLAG_KEY;
yading@11 1219 }
yading@11 1220
yading@11 1221 /* read data */
yading@11 1222 av_dlog(asf, "READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n",
yading@11 1223 s->packet_size, asf_st->pkt.size, asf->packet_frag_offset,
yading@11 1224 asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data);
yading@11 1225 asf->packet_size_left -= asf->packet_frag_size;
yading@11 1226 if (asf->packet_size_left < 0)
yading@11 1227 continue;
yading@11 1228
yading@11 1229 if (asf->packet_frag_offset >= asf_st->pkt.size ||
yading@11 1230 asf->packet_frag_size > asf_st->pkt.size - asf->packet_frag_offset) {
yading@11 1231 av_log(s, AV_LOG_ERROR,
yading@11 1232 "packet fragment position invalid %u,%u not in %u\n",
yading@11 1233 asf->packet_frag_offset, asf->packet_frag_size,
yading@11 1234 asf_st->pkt.size);
yading@11 1235 continue;
yading@11 1236 }
yading@11 1237
yading@11 1238 ret = avio_read(pb, asf_st->pkt.data + asf->packet_frag_offset,
yading@11 1239 asf->packet_frag_size);
yading@11 1240 if (ret != asf->packet_frag_size) {
yading@11 1241 if (ret < 0 || asf->packet_frag_offset + ret == 0)
yading@11 1242 return ret < 0 ? ret : AVERROR_EOF;
yading@11 1243
yading@11 1244 if (asf_st->ds_span > 1) {
yading@11 1245 // scrambling, we can either drop it completely or fill the remainder
yading@11 1246 // TODO: should we fill the whole packet instead of just the current
yading@11 1247 // fragment?
yading@11 1248 memset(asf_st->pkt.data + asf->packet_frag_offset + ret, 0,
yading@11 1249 asf->packet_frag_size - ret);
yading@11 1250 ret = asf->packet_frag_size;
yading@11 1251 } else {
yading@11 1252 // no scrambling, so we can return partial packets
yading@11 1253 av_shrink_packet(&asf_st->pkt, asf->packet_frag_offset + ret);
yading@11 1254 }
yading@11 1255 }
yading@11 1256 if (s->key && s->keylen == 20)
yading@11 1257 ff_asfcrypt_dec(s->key, asf_st->pkt.data + asf->packet_frag_offset,
yading@11 1258 ret);
yading@11 1259 asf_st->frag_offset += ret;
yading@11 1260 /* test if whole packet is read */
yading@11 1261 if (asf_st->frag_offset == asf_st->pkt.size) {
yading@11 1262 // workaround for macroshit radio DVR-MS files
yading@11 1263 if (s->streams[asf->stream_index]->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
yading@11 1264 asf_st->pkt.size > 100) {
yading@11 1265 int i;
yading@11 1266 for (i = 0; i < asf_st->pkt.size && !asf_st->pkt.data[i]; i++)
yading@11 1267 ;
yading@11 1268 if (i == asf_st->pkt.size) {
yading@11 1269 av_log(s, AV_LOG_DEBUG, "discarding ms fart\n");
yading@11 1270 asf_st->frag_offset = 0;
yading@11 1271 av_free_packet(&asf_st->pkt);
yading@11 1272 continue;
yading@11 1273 }
yading@11 1274 }
yading@11 1275
yading@11 1276 /* return packet */
yading@11 1277 if (asf_st->ds_span > 1) {
yading@11 1278 if (asf_st->pkt.size != asf_st->ds_packet_size * asf_st->ds_span) {
yading@11 1279 av_log(s, AV_LOG_ERROR,
yading@11 1280 "pkt.size != ds_packet_size * ds_span (%d %d %d)\n",
yading@11 1281 asf_st->pkt.size, asf_st->ds_packet_size,
yading@11 1282 asf_st->ds_span);
yading@11 1283 } else {
yading@11 1284 /* packet descrambling */
yading@11 1285 AVBufferRef *buf = av_buffer_alloc(asf_st->pkt.size +
yading@11 1286 FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 1287 if (buf) {
yading@11 1288 uint8_t *newdata = buf->data;
yading@11 1289 int offset = 0;
yading@11 1290 memset(newdata + asf_st->pkt.size, 0,
yading@11 1291 FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 1292 while (offset < asf_st->pkt.size) {
yading@11 1293 int off = offset / asf_st->ds_chunk_size;
yading@11 1294 int row = off / asf_st->ds_span;
yading@11 1295 int col = off % asf_st->ds_span;
yading@11 1296 int idx = row + col * asf_st->ds_packet_size / asf_st->ds_chunk_size;
yading@11 1297 assert(offset + asf_st->ds_chunk_size <= asf_st->pkt.size);
yading@11 1298 assert(idx + 1 <= asf_st->pkt.size / asf_st->ds_chunk_size);
yading@11 1299 memcpy(newdata + offset,
yading@11 1300 asf_st->pkt.data + idx * asf_st->ds_chunk_size,
yading@11 1301 asf_st->ds_chunk_size);
yading@11 1302 offset += asf_st->ds_chunk_size;
yading@11 1303 }
yading@11 1304 av_buffer_unref(&asf_st->pkt.buf);
yading@11 1305 asf_st->pkt.buf = buf;
yading@11 1306 asf_st->pkt.data = buf->data;
yading@11 1307 }
yading@11 1308 }
yading@11 1309 }
yading@11 1310 asf_st->frag_offset = 0;
yading@11 1311 *pkt = asf_st->pkt;
yading@11 1312 #if FF_API_DESTRUCT_PACKET
yading@11 1313 asf_st->pkt.destruct = NULL;
yading@11 1314 #endif
yading@11 1315 asf_st->pkt.buf = 0;
yading@11 1316 asf_st->pkt.size = 0;
yading@11 1317 asf_st->pkt.data = 0;
yading@11 1318 asf_st->pkt.side_data_elems = 0;
yading@11 1319 asf_st->pkt.side_data = NULL;
yading@11 1320 break; // packet completed
yading@11 1321 }
yading@11 1322 }
yading@11 1323 return 0;
yading@11 1324 }
yading@11 1325
yading@11 1326 static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
yading@11 1327 {
yading@11 1328 ASFContext *asf = s->priv_data;
yading@11 1329
yading@11 1330 for (;;) {
yading@11 1331 int ret;
yading@11 1332
yading@11 1333 /* parse cached packets, if any */
yading@11 1334 if ((ret = ff_asf_parse_packet(s, s->pb, pkt)) <= 0)
yading@11 1335 return ret;
yading@11 1336 if ((ret = ff_asf_get_packet(s, s->pb)) < 0)
yading@11 1337 assert(asf->packet_size_left < FRAME_HEADER_SIZE ||
yading@11 1338 asf->packet_segments < 1);
yading@11 1339 asf->packet_time_start = 0;
yading@11 1340 }
yading@11 1341 }
yading@11 1342
yading@11 1343 // Added to support seeking after packets have been read
yading@11 1344 // If information is not reset, read_packet fails due to
yading@11 1345 // leftover information from previous reads
yading@11 1346 static void asf_reset_header(AVFormatContext *s)
yading@11 1347 {
yading@11 1348 ASFContext *asf = s->priv_data;
yading@11 1349 ASFStream *asf_st;
yading@11 1350 int i;
yading@11 1351
yading@11 1352 asf->packet_size_left = 0;
yading@11 1353 asf->packet_segments = 0;
yading@11 1354 asf->packet_flags = 0;
yading@11 1355 asf->packet_property = 0;
yading@11 1356 asf->packet_timestamp = 0;
yading@11 1357 asf->packet_segsizetype = 0;
yading@11 1358 asf->packet_segments = 0;
yading@11 1359 asf->packet_seq = 0;
yading@11 1360 asf->packet_replic_size = 0;
yading@11 1361 asf->packet_key_frame = 0;
yading@11 1362 asf->packet_padsize = 0;
yading@11 1363 asf->packet_frag_offset = 0;
yading@11 1364 asf->packet_frag_size = 0;
yading@11 1365 asf->packet_frag_timestamp = 0;
yading@11 1366 asf->packet_multi_size = 0;
yading@11 1367 asf->packet_obj_size = 0;
yading@11 1368 asf->packet_time_delta = 0;
yading@11 1369 asf->packet_time_start = 0;
yading@11 1370
yading@11 1371 for (i = 0; i < s->nb_streams; i++) {
yading@11 1372 asf_st = s->streams[i]->priv_data;
yading@11 1373 if (!asf_st)
yading@11 1374 continue;
yading@11 1375 av_free_packet(&asf_st->pkt);
yading@11 1376 asf_st->frag_offset = 0;
yading@11 1377 asf_st->seq = 0;
yading@11 1378 }
yading@11 1379 asf->asf_st = NULL;
yading@11 1380 }
yading@11 1381
yading@11 1382 static int asf_read_close(AVFormatContext *s)
yading@11 1383 {
yading@11 1384 asf_reset_header(s);
yading@11 1385
yading@11 1386 return 0;
yading@11 1387 }
yading@11 1388
yading@11 1389 static int64_t asf_read_pts(AVFormatContext *s, int stream_index,
yading@11 1390 int64_t *ppos, int64_t pos_limit)
yading@11 1391 {
yading@11 1392 AVPacket pkt1, *pkt = &pkt1;
yading@11 1393 ASFStream *asf_st;
yading@11 1394 int64_t pts;
yading@11 1395 int64_t pos = *ppos;
yading@11 1396 int i;
yading@11 1397 int64_t start_pos[ASF_MAX_STREAMS];
yading@11 1398
yading@11 1399 for (i = 0; i < s->nb_streams; i++)
yading@11 1400 start_pos[i] = pos;
yading@11 1401
yading@11 1402 if (s->packet_size > 0)
yading@11 1403 pos = (pos + s->packet_size - 1 - s->data_offset) /
yading@11 1404 s->packet_size * s->packet_size +
yading@11 1405 s->data_offset;
yading@11 1406 *ppos = pos;
yading@11 1407 if (avio_seek(s->pb, pos, SEEK_SET) < 0)
yading@11 1408 return AV_NOPTS_VALUE;
yading@11 1409
yading@11 1410 asf_reset_header(s);
yading@11 1411 for (;;) {
yading@11 1412 if (av_read_frame(s, pkt) < 0) {
yading@11 1413 av_log(s, AV_LOG_INFO, "asf_read_pts failed\n");
yading@11 1414 return AV_NOPTS_VALUE;
yading@11 1415 }
yading@11 1416
yading@11 1417 pts = pkt->dts;
yading@11 1418
yading@11 1419 av_free_packet(pkt);
yading@11 1420 if (pkt->flags & AV_PKT_FLAG_KEY) {
yading@11 1421 i = pkt->stream_index;
yading@11 1422
yading@11 1423 asf_st = s->streams[i]->priv_data;
yading@11 1424 av_assert0(asf_st);
yading@11 1425
yading@11 1426 // assert((asf_st->packet_pos - s->data_offset) % s->packet_size == 0);
yading@11 1427 pos = asf_st->packet_pos;
yading@11 1428
yading@11 1429 av_add_index_entry(s->streams[i], pos, pts, pkt->size,
yading@11 1430 pos - start_pos[i] + 1, AVINDEX_KEYFRAME);
yading@11 1431 start_pos[i] = asf_st->packet_pos + 1;
yading@11 1432
yading@11 1433 if (pkt->stream_index == stream_index)
yading@11 1434 break;
yading@11 1435 }
yading@11 1436 }
yading@11 1437
yading@11 1438 *ppos = pos;
yading@11 1439 return pts;
yading@11 1440 }
yading@11 1441
yading@11 1442 static void asf_build_simple_index(AVFormatContext *s, int stream_index)
yading@11 1443 {
yading@11 1444 ff_asf_guid g;
yading@11 1445 ASFContext *asf = s->priv_data;
yading@11 1446 int64_t current_pos = avio_tell(s->pb);
yading@11 1447
yading@11 1448 if(avio_seek(s->pb, asf->data_object_offset + asf->data_object_size, SEEK_SET) < 0) {
yading@11 1449 asf->index_read= -1;
yading@11 1450 return;
yading@11 1451 }
yading@11 1452
yading@11 1453 ff_get_guid(s->pb, &g);
yading@11 1454
yading@11 1455 /* the data object can be followed by other top-level objects,
yading@11 1456 * skip them until the simple index object is reached */
yading@11 1457 while (ff_guidcmp(&g, &ff_asf_simple_index_header)) {
yading@11 1458 int64_t gsize = avio_rl64(s->pb);
yading@11 1459 if (gsize < 24 || url_feof(s->pb)) {
yading@11 1460 avio_seek(s->pb, current_pos, SEEK_SET);
yading@11 1461 asf->index_read= -1;
yading@11 1462 return;
yading@11 1463 }
yading@11 1464 avio_skip(s->pb, gsize - 24);
yading@11 1465 ff_get_guid(s->pb, &g);
yading@11 1466 }
yading@11 1467
yading@11 1468 {
yading@11 1469 int64_t itime, last_pos = -1;
yading@11 1470 int pct, ict;
yading@11 1471 int i;
yading@11 1472 int64_t av_unused gsize = avio_rl64(s->pb);
yading@11 1473 ff_get_guid(s->pb, &g);
yading@11 1474 itime = avio_rl64(s->pb);
yading@11 1475 pct = avio_rl32(s->pb);
yading@11 1476 ict = avio_rl32(s->pb);
yading@11 1477 av_log(s, AV_LOG_DEBUG,
yading@11 1478 "itime:0x%"PRIx64", pct:%d, ict:%d\n", itime, pct, ict);
yading@11 1479
yading@11 1480 for (i = 0; i < ict; i++) {
yading@11 1481 int pktnum = avio_rl32(s->pb);
yading@11 1482 int pktct = avio_rl16(s->pb);
yading@11 1483 int64_t pos = s->data_offset + s->packet_size * (int64_t)pktnum;
yading@11 1484 int64_t index_pts = FFMAX(av_rescale(itime, i, 10000) - asf->hdr.preroll, 0);
yading@11 1485
yading@11 1486 if (pos != last_pos) {
yading@11 1487 av_log(s, AV_LOG_DEBUG, "pktnum:%d, pktct:%d pts: %"PRId64"\n",
yading@11 1488 pktnum, pktct, index_pts);
yading@11 1489 av_add_index_entry(s->streams[stream_index], pos, index_pts,
yading@11 1490 s->packet_size, 0, AVINDEX_KEYFRAME);
yading@11 1491 last_pos = pos;
yading@11 1492 }
yading@11 1493 }
yading@11 1494 asf->index_read = ict > 1;
yading@11 1495 }
yading@11 1496 avio_seek(s->pb, current_pos, SEEK_SET);
yading@11 1497 }
yading@11 1498
yading@11 1499 static int asf_read_seek(AVFormatContext *s, int stream_index,
yading@11 1500 int64_t pts, int flags)
yading@11 1501 {
yading@11 1502 ASFContext *asf = s->priv_data;
yading@11 1503 AVStream *st = s->streams[stream_index];
yading@11 1504
yading@11 1505 if (s->packet_size <= 0)
yading@11 1506 return -1;
yading@11 1507
yading@11 1508 /* Try using the protocol's read_seek if available */
yading@11 1509 if (s->pb) {
yading@11 1510 int ret = avio_seek_time(s->pb, stream_index, pts, flags);
yading@11 1511 if (ret >= 0)
yading@11 1512 asf_reset_header(s);
yading@11 1513 if (ret != AVERROR(ENOSYS))
yading@11 1514 return ret;
yading@11 1515 }
yading@11 1516
yading@11 1517 if (!asf->index_read)
yading@11 1518 asf_build_simple_index(s, stream_index);
yading@11 1519
yading@11 1520 if ((asf->index_read > 0 && st->index_entries)) {
yading@11 1521 int index = av_index_search_timestamp(st, pts, flags);
yading@11 1522 if (index >= 0) {
yading@11 1523 /* find the position */
yading@11 1524 uint64_t pos = st->index_entries[index].pos;
yading@11 1525
yading@11 1526 /* do the seek */
yading@11 1527 av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
yading@11 1528 if(avio_seek(s->pb, pos, SEEK_SET) < 0)
yading@11 1529 return -1;
yading@11 1530 asf_reset_header(s);
yading@11 1531 return 0;
yading@11 1532 }
yading@11 1533 }
yading@11 1534 /* no index or seeking by index failed */
yading@11 1535 if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0)
yading@11 1536 return -1;
yading@11 1537 asf_reset_header(s);
yading@11 1538 return 0;
yading@11 1539 }
yading@11 1540
yading@11 1541 AVInputFormat ff_asf_demuxer = {
yading@11 1542 .name = "asf",
yading@11 1543 .long_name = NULL_IF_CONFIG_SMALL("ASF (Advanced / Active Streaming Format)"),
yading@11 1544 .priv_data_size = sizeof(ASFContext),
yading@11 1545 .read_probe = asf_probe,
yading@11 1546 .read_header = asf_read_header,
yading@11 1547 .read_packet = asf_read_packet,
yading@11 1548 .read_close = asf_read_close,
yading@11 1549 .read_seek = asf_read_seek,
yading@11 1550 .read_timestamp = asf_read_pts,
yading@11 1551 .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH,
yading@11 1552 .priv_class = &asf_class,
yading@11 1553 };