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