1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * "Real" 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/avassert.h" 25cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h" 26cabdff1aSopenharmony_ci#include "libavutil/internal.h" 27cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 28cabdff1aSopenharmony_ci#include "libavutil/dict.h" 29cabdff1aSopenharmony_ci#include "avformat.h" 30cabdff1aSopenharmony_ci#include "avio_internal.h" 31cabdff1aSopenharmony_ci#include "demux.h" 32cabdff1aSopenharmony_ci#include "internal.h" 33cabdff1aSopenharmony_ci#include "rmsipr.h" 34cabdff1aSopenharmony_ci#include "rm.h" 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci#define DEINT_ID_GENR MKTAG('g', 'e', 'n', 'r') ///< interleaving for Cooker/ATRAC 37cabdff1aSopenharmony_ci#define DEINT_ID_INT0 MKTAG('I', 'n', 't', '0') ///< no interleaving needed 38cabdff1aSopenharmony_ci#define DEINT_ID_INT4 MKTAG('I', 'n', 't', '4') ///< interleaving for 28.8 39cabdff1aSopenharmony_ci#define DEINT_ID_SIPR MKTAG('s', 'i', 'p', 'r') ///< interleaving for Sipro 40cabdff1aSopenharmony_ci#define DEINT_ID_VBRF MKTAG('v', 'b', 'r', 'f') ///< VBR case for AAC 41cabdff1aSopenharmony_ci#define DEINT_ID_VBRS MKTAG('v', 'b', 'r', 's') ///< VBR case for AAC 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_cistruct RMStream { 44cabdff1aSopenharmony_ci AVPacket pkt; ///< place to store merged video frame / reordered audio data 45cabdff1aSopenharmony_ci int videobufsize; ///< current assembled frame size 46cabdff1aSopenharmony_ci int videobufpos; ///< position for the next slice in the video buffer 47cabdff1aSopenharmony_ci int curpic_num; ///< picture number of current frame 48cabdff1aSopenharmony_ci int cur_slice, slices; 49cabdff1aSopenharmony_ci int64_t pktpos; ///< first slice position in file 50cabdff1aSopenharmony_ci /// Audio descrambling matrix parameters 51cabdff1aSopenharmony_ci int64_t audiotimestamp; ///< Audio packet timestamp 52cabdff1aSopenharmony_ci int sub_packet_cnt; // Subpacket counter, used while reading 53cabdff1aSopenharmony_ci int sub_packet_size, sub_packet_h, coded_framesize; ///< Descrambling parameters from container 54cabdff1aSopenharmony_ci int audio_framesize; /// Audio frame size from container 55cabdff1aSopenharmony_ci int sub_packet_lengths[16]; /// Length of each subpacket 56cabdff1aSopenharmony_ci int32_t deint_id; ///< deinterleaver used in audio stream 57cabdff1aSopenharmony_ci}; 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_citypedef struct RMDemuxContext { 60cabdff1aSopenharmony_ci int nb_packets; 61cabdff1aSopenharmony_ci int old_format; 62cabdff1aSopenharmony_ci int current_stream; 63cabdff1aSopenharmony_ci int remaining_len; 64cabdff1aSopenharmony_ci int audio_stream_num; ///< Stream number for audio packets 65cabdff1aSopenharmony_ci int audio_pkt_cnt; ///< Output packet counter 66cabdff1aSopenharmony_ci int data_end; 67cabdff1aSopenharmony_ci} RMDemuxContext; 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_cistatic inline void get_strl(AVIOContext *pb, char *buf, int buf_size, int len) 70cabdff1aSopenharmony_ci{ 71cabdff1aSopenharmony_ci int read = avio_get_str(pb, len, buf, buf_size); 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci if (read > 0) 74cabdff1aSopenharmony_ci avio_skip(pb, len - read); 75cabdff1aSopenharmony_ci} 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_cistatic void get_str8(AVIOContext *pb, char *buf, int buf_size) 78cabdff1aSopenharmony_ci{ 79cabdff1aSopenharmony_ci get_strl(pb, buf, buf_size, avio_r8(pb)); 80cabdff1aSopenharmony_ci} 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_cistatic int rm_read_extradata(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, unsigned size) 83cabdff1aSopenharmony_ci{ 84cabdff1aSopenharmony_ci if (size >= 1<<24) { 85cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "extradata size %u too large\n", size); 86cabdff1aSopenharmony_ci return -1; 87cabdff1aSopenharmony_ci } 88cabdff1aSopenharmony_ci return ff_get_extradata(s, par, pb, size); 89cabdff1aSopenharmony_ci} 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_cistatic void rm_read_metadata(AVFormatContext *s, AVIOContext *pb, int wide) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci char buf[1024]; 94cabdff1aSopenharmony_ci int i; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci for (i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { 97cabdff1aSopenharmony_ci int len = wide ? avio_rb16(pb) : avio_r8(pb); 98cabdff1aSopenharmony_ci if (len > 0) { 99cabdff1aSopenharmony_ci get_strl(pb, buf, sizeof(buf), len); 100cabdff1aSopenharmony_ci av_dict_set(&s->metadata, ff_rm_metadata[i], buf, 0); 101cabdff1aSopenharmony_ci } 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci} 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ciRMStream *ff_rm_alloc_rmstream (void) 106cabdff1aSopenharmony_ci{ 107cabdff1aSopenharmony_ci RMStream *rms = av_mallocz(sizeof(RMStream)); 108cabdff1aSopenharmony_ci if (!rms) 109cabdff1aSopenharmony_ci return NULL; 110cabdff1aSopenharmony_ci rms->curpic_num = -1; 111cabdff1aSopenharmony_ci return rms; 112cabdff1aSopenharmony_ci} 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_civoid ff_rm_free_rmstream (RMStream *rms) 115cabdff1aSopenharmony_ci{ 116cabdff1aSopenharmony_ci if (!rms) 117cabdff1aSopenharmony_ci return; 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci av_packet_unref(&rms->pkt); 120cabdff1aSopenharmony_ci} 121cabdff1aSopenharmony_ci 122cabdff1aSopenharmony_cistatic int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, 123cabdff1aSopenharmony_ci AVStream *st, RMStream *ast, int read_all) 124cabdff1aSopenharmony_ci{ 125cabdff1aSopenharmony_ci FFStream *const sti = ffstream(st); 126cabdff1aSopenharmony_ci char buf[256]; 127cabdff1aSopenharmony_ci uint32_t version; 128cabdff1aSopenharmony_ci int ret; 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_ci /* ra type header */ 131cabdff1aSopenharmony_ci version = avio_rb16(pb); /* version */ 132cabdff1aSopenharmony_ci if (version == 3) { 133cabdff1aSopenharmony_ci unsigned bytes_per_minute; 134cabdff1aSopenharmony_ci int header_size = avio_rb16(pb); 135cabdff1aSopenharmony_ci int64_t startpos = avio_tell(pb); 136cabdff1aSopenharmony_ci avio_skip(pb, 8); 137cabdff1aSopenharmony_ci bytes_per_minute = avio_rb16(pb); 138cabdff1aSopenharmony_ci avio_skip(pb, 4); 139cabdff1aSopenharmony_ci rm_read_metadata(s, pb, 0); 140cabdff1aSopenharmony_ci if ((startpos + header_size) >= avio_tell(pb) + 2) { 141cabdff1aSopenharmony_ci // fourcc (should always be "lpcJ") 142cabdff1aSopenharmony_ci avio_r8(pb); 143cabdff1aSopenharmony_ci get_str8(pb, buf, sizeof(buf)); 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci // Skip extra header crap (this should never happen) 146cabdff1aSopenharmony_ci if ((startpos + header_size) > avio_tell(pb)) 147cabdff1aSopenharmony_ci avio_skip(pb, header_size + startpos - avio_tell(pb)); 148cabdff1aSopenharmony_ci if (bytes_per_minute) 149cabdff1aSopenharmony_ci st->codecpar->bit_rate = 8LL * bytes_per_minute / 60; 150cabdff1aSopenharmony_ci st->codecpar->sample_rate = 8000; 151cabdff1aSopenharmony_ci st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; 152cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 153cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_RA_144; 154cabdff1aSopenharmony_ci ast->deint_id = DEINT_ID_INT0; 155cabdff1aSopenharmony_ci } else { 156cabdff1aSopenharmony_ci int flavor, sub_packet_h, coded_framesize, sub_packet_size; 157cabdff1aSopenharmony_ci int codecdata_length; 158cabdff1aSopenharmony_ci unsigned bytes_per_minute; 159cabdff1aSopenharmony_ci /* old version (4) */ 160cabdff1aSopenharmony_ci avio_skip(pb, 2); /* unused */ 161cabdff1aSopenharmony_ci avio_rb32(pb); /* .ra4 */ 162cabdff1aSopenharmony_ci avio_rb32(pb); /* data size */ 163cabdff1aSopenharmony_ci avio_rb16(pb); /* version2 */ 164cabdff1aSopenharmony_ci avio_rb32(pb); /* header size */ 165cabdff1aSopenharmony_ci flavor= avio_rb16(pb); /* add codec info / flavor */ 166cabdff1aSopenharmony_ci coded_framesize = avio_rb32(pb); /* coded frame size */ 167cabdff1aSopenharmony_ci if (coded_framesize < 0) 168cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 169cabdff1aSopenharmony_ci ast->coded_framesize = coded_framesize; 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_ci avio_rb32(pb); /* ??? */ 172cabdff1aSopenharmony_ci bytes_per_minute = avio_rb32(pb); 173cabdff1aSopenharmony_ci if (version == 4) { 174cabdff1aSopenharmony_ci if (bytes_per_minute) 175cabdff1aSopenharmony_ci st->codecpar->bit_rate = 8LL * bytes_per_minute / 60; 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci avio_rb32(pb); /* ??? */ 178cabdff1aSopenharmony_ci ast->sub_packet_h = sub_packet_h = avio_rb16(pb); /* 1 */ 179cabdff1aSopenharmony_ci st->codecpar->block_align= avio_rb16(pb); /* frame size */ 180cabdff1aSopenharmony_ci ast->sub_packet_size = sub_packet_size = avio_rb16(pb); /* sub packet size */ 181cabdff1aSopenharmony_ci avio_rb16(pb); /* ??? */ 182cabdff1aSopenharmony_ci if (version == 5) { 183cabdff1aSopenharmony_ci avio_rb16(pb); avio_rb16(pb); avio_rb16(pb); 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci st->codecpar->sample_rate = avio_rb16(pb); 186cabdff1aSopenharmony_ci avio_rb32(pb); 187cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels = avio_rb16(pb); 188cabdff1aSopenharmony_ci if (version == 5) { 189cabdff1aSopenharmony_ci ast->deint_id = avio_rl32(pb); 190cabdff1aSopenharmony_ci avio_read(pb, buf, 4); 191cabdff1aSopenharmony_ci buf[4] = 0; 192cabdff1aSopenharmony_ci } else { 193cabdff1aSopenharmony_ci AV_WL32(buf, 0); 194cabdff1aSopenharmony_ci get_str8(pb, buf, sizeof(buf)); /* desc */ 195cabdff1aSopenharmony_ci ast->deint_id = AV_RL32(buf); 196cabdff1aSopenharmony_ci get_str8(pb, buf, sizeof(buf)); /* desc */ 197cabdff1aSopenharmony_ci } 198cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 199cabdff1aSopenharmony_ci st->codecpar->codec_tag = AV_RL32(buf); 200cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_rm_codec_tags, 201cabdff1aSopenharmony_ci st->codecpar->codec_tag); 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci switch (st->codecpar->codec_id) { 204cabdff1aSopenharmony_ci case AV_CODEC_ID_AC3: 205cabdff1aSopenharmony_ci sti->need_parsing = AVSTREAM_PARSE_FULL; 206cabdff1aSopenharmony_ci break; 207cabdff1aSopenharmony_ci case AV_CODEC_ID_RA_288: 208cabdff1aSopenharmony_ci st->codecpar->extradata_size= 0; 209cabdff1aSopenharmony_ci av_freep(&st->codecpar->extradata); 210cabdff1aSopenharmony_ci ast->audio_framesize = st->codecpar->block_align; 211cabdff1aSopenharmony_ci st->codecpar->block_align = coded_framesize; 212cabdff1aSopenharmony_ci break; 213cabdff1aSopenharmony_ci case AV_CODEC_ID_COOK: 214cabdff1aSopenharmony_ci sti->need_parsing = AVSTREAM_PARSE_HEADERS; 215cabdff1aSopenharmony_ci case AV_CODEC_ID_ATRAC3: 216cabdff1aSopenharmony_ci case AV_CODEC_ID_SIPR: 217cabdff1aSopenharmony_ci if (read_all) { 218cabdff1aSopenharmony_ci codecdata_length = 0; 219cabdff1aSopenharmony_ci } else { 220cabdff1aSopenharmony_ci avio_rb16(pb); avio_r8(pb); 221cabdff1aSopenharmony_ci if (version == 5) 222cabdff1aSopenharmony_ci avio_r8(pb); 223cabdff1aSopenharmony_ci codecdata_length = avio_rb32(pb); 224cabdff1aSopenharmony_ci if((unsigned)codecdata_length > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE){ 225cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); 226cabdff1aSopenharmony_ci return -1; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci ast->audio_framesize = st->codecpar->block_align; 231cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) { 232cabdff1aSopenharmony_ci if (flavor > 3) { 233cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "bad SIPR file flavor %d\n", 234cabdff1aSopenharmony_ci flavor); 235cabdff1aSopenharmony_ci return -1; 236cabdff1aSopenharmony_ci } 237cabdff1aSopenharmony_ci st->codecpar->block_align = ff_sipr_subpk_size[flavor]; 238cabdff1aSopenharmony_ci sti->need_parsing = AVSTREAM_PARSE_FULL_RAW; 239cabdff1aSopenharmony_ci } else { 240cabdff1aSopenharmony_ci if(sub_packet_size <= 0){ 241cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "sub_packet_size is invalid\n"); 242cabdff1aSopenharmony_ci return -1; 243cabdff1aSopenharmony_ci } 244cabdff1aSopenharmony_ci st->codecpar->block_align = ast->sub_packet_size; 245cabdff1aSopenharmony_ci } 246cabdff1aSopenharmony_ci if ((ret = rm_read_extradata(s, pb, st->codecpar, codecdata_length)) < 0) 247cabdff1aSopenharmony_ci return ret; 248cabdff1aSopenharmony_ci 249cabdff1aSopenharmony_ci break; 250cabdff1aSopenharmony_ci case AV_CODEC_ID_AAC: 251cabdff1aSopenharmony_ci avio_rb16(pb); avio_r8(pb); 252cabdff1aSopenharmony_ci if (version == 5) 253cabdff1aSopenharmony_ci avio_r8(pb); 254cabdff1aSopenharmony_ci codecdata_length = avio_rb32(pb); 255cabdff1aSopenharmony_ci if((unsigned)codecdata_length > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE){ 256cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "codecdata_length too large\n"); 257cabdff1aSopenharmony_ci return -1; 258cabdff1aSopenharmony_ci } 259cabdff1aSopenharmony_ci if (codecdata_length >= 1) { 260cabdff1aSopenharmony_ci avio_r8(pb); 261cabdff1aSopenharmony_ci if ((ret = rm_read_extradata(s, pb, st->codecpar, codecdata_length - 1)) < 0) 262cabdff1aSopenharmony_ci return ret; 263cabdff1aSopenharmony_ci } 264cabdff1aSopenharmony_ci break; 265cabdff1aSopenharmony_ci } 266cabdff1aSopenharmony_ci switch (ast->deint_id) { 267cabdff1aSopenharmony_ci case DEINT_ID_INT4: 268cabdff1aSopenharmony_ci if (ast->coded_framesize > ast->audio_framesize || 269cabdff1aSopenharmony_ci sub_packet_h <= 1 || 270cabdff1aSopenharmony_ci ast->coded_framesize * (uint64_t)sub_packet_h > (2 + (sub_packet_h & 1)) * ast->audio_framesize) 271cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 272cabdff1aSopenharmony_ci if (ast->coded_framesize * (uint64_t)sub_packet_h != 2*ast->audio_framesize) { 273cabdff1aSopenharmony_ci avpriv_request_sample(s, "mismatching interleaver parameters"); 274cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 275cabdff1aSopenharmony_ci } 276cabdff1aSopenharmony_ci break; 277cabdff1aSopenharmony_ci case DEINT_ID_GENR: 278cabdff1aSopenharmony_ci if (ast->sub_packet_size <= 0 || 279cabdff1aSopenharmony_ci ast->sub_packet_size > ast->audio_framesize) 280cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 281cabdff1aSopenharmony_ci if (ast->audio_framesize % ast->sub_packet_size) 282cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 283cabdff1aSopenharmony_ci break; 284cabdff1aSopenharmony_ci case DEINT_ID_SIPR: 285cabdff1aSopenharmony_ci case DEINT_ID_INT0: 286cabdff1aSopenharmony_ci case DEINT_ID_VBRS: 287cabdff1aSopenharmony_ci case DEINT_ID_VBRF: 288cabdff1aSopenharmony_ci break; 289cabdff1aSopenharmony_ci default: 290cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR ,"Unknown interleaver %"PRIX32"\n", ast->deint_id); 291cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 292cabdff1aSopenharmony_ci } 293cabdff1aSopenharmony_ci if (ast->deint_id == DEINT_ID_INT4 || 294cabdff1aSopenharmony_ci ast->deint_id == DEINT_ID_GENR || 295cabdff1aSopenharmony_ci ast->deint_id == DEINT_ID_SIPR) { 296cabdff1aSopenharmony_ci if (st->codecpar->block_align <= 0 || 297cabdff1aSopenharmony_ci ast->audio_framesize * (uint64_t)sub_packet_h > (unsigned)INT_MAX || 298cabdff1aSopenharmony_ci ast->audio_framesize * sub_packet_h < st->codecpar->block_align) 299cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 300cabdff1aSopenharmony_ci if (av_new_packet(&ast->pkt, ast->audio_framesize * sub_packet_h) < 0) 301cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 302cabdff1aSopenharmony_ci } 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci if (read_all) { 305cabdff1aSopenharmony_ci avio_r8(pb); 306cabdff1aSopenharmony_ci avio_r8(pb); 307cabdff1aSopenharmony_ci avio_r8(pb); 308cabdff1aSopenharmony_ci rm_read_metadata(s, pb, 0); 309cabdff1aSopenharmony_ci } 310cabdff1aSopenharmony_ci } 311cabdff1aSopenharmony_ci return 0; 312cabdff1aSopenharmony_ci} 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ciint ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb, 315cabdff1aSopenharmony_ci AVStream *st, RMStream *rst, 316cabdff1aSopenharmony_ci unsigned int codec_data_size, const uint8_t *mime) 317cabdff1aSopenharmony_ci{ 318cabdff1aSopenharmony_ci unsigned int v; 319cabdff1aSopenharmony_ci int size; 320cabdff1aSopenharmony_ci int64_t codec_pos; 321cabdff1aSopenharmony_ci int ret; 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ci if (codec_data_size > INT_MAX) 324cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 325cabdff1aSopenharmony_ci if (codec_data_size == 0) 326cabdff1aSopenharmony_ci return 0; 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci // Duplicate tags 329cabdff1aSopenharmony_ci if ( st->codecpar->codec_type != AVMEDIA_TYPE_UNKNOWN 330cabdff1aSopenharmony_ci && st->codecpar->codec_type != AVMEDIA_TYPE_DATA) 331cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, 1, 1000); 334cabdff1aSopenharmony_ci codec_pos = avio_tell(pb); 335cabdff1aSopenharmony_ci v = avio_rb32(pb); 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci if (v == MKTAG(0xfd, 'a', 'r', '.')) { 338cabdff1aSopenharmony_ci /* ra type header */ 339cabdff1aSopenharmony_ci if (rm_read_audio_stream_info(s, pb, st, rst, 0)) 340cabdff1aSopenharmony_ci return -1; 341cabdff1aSopenharmony_ci } else if (v == MKBETAG('L', 'S', 'D', ':')) { 342cabdff1aSopenharmony_ci avio_seek(pb, -4, SEEK_CUR); 343cabdff1aSopenharmony_ci if ((ret = rm_read_extradata(s, pb, st->codecpar, codec_data_size)) < 0) 344cabdff1aSopenharmony_ci return ret; 345cabdff1aSopenharmony_ci 346cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 347cabdff1aSopenharmony_ci st->codecpar->codec_tag = AV_RL32(st->codecpar->extradata); 348cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_rm_codec_tags, 349cabdff1aSopenharmony_ci st->codecpar->codec_tag); 350cabdff1aSopenharmony_ci } else if(mime && !strcmp(mime, "logical-fileinfo")){ 351cabdff1aSopenharmony_ci int stream_count, rule_count, property_count, i; 352cabdff1aSopenharmony_ci ff_remove_stream(s, st); 353cabdff1aSopenharmony_ci if (avio_rb16(pb) != 0) { 354cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Unsupported version\n"); 355cabdff1aSopenharmony_ci goto skip; 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci stream_count = avio_rb16(pb); 358cabdff1aSopenharmony_ci avio_skip(pb, 6*stream_count); 359cabdff1aSopenharmony_ci rule_count = avio_rb16(pb); 360cabdff1aSopenharmony_ci avio_skip(pb, 2*rule_count); 361cabdff1aSopenharmony_ci property_count = avio_rb16(pb); 362cabdff1aSopenharmony_ci for(i=0; i<property_count; i++){ 363cabdff1aSopenharmony_ci uint8_t name[128], val[128]; 364cabdff1aSopenharmony_ci avio_rb32(pb); 365cabdff1aSopenharmony_ci if (avio_rb16(pb) != 0) { 366cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Unsupported Name value property version\n"); 367cabdff1aSopenharmony_ci goto skip; //FIXME skip just this one 368cabdff1aSopenharmony_ci } 369cabdff1aSopenharmony_ci get_str8(pb, name, sizeof(name)); 370cabdff1aSopenharmony_ci switch(avio_rb32(pb)) { 371cabdff1aSopenharmony_ci case 2: get_strl(pb, val, sizeof(val), avio_rb16(pb)); 372cabdff1aSopenharmony_ci av_dict_set(&s->metadata, name, val, 0); 373cabdff1aSopenharmony_ci break; 374cabdff1aSopenharmony_ci default: avio_skip(pb, avio_rb16(pb)); 375cabdff1aSopenharmony_ci } 376cabdff1aSopenharmony_ci } 377cabdff1aSopenharmony_ci } else { 378cabdff1aSopenharmony_ci int fps; 379cabdff1aSopenharmony_ci if (avio_rl32(pb) != MKTAG('V', 'I', 'D', 'O')) { 380cabdff1aSopenharmony_ci fail1: 381cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "Unsupported stream type %08x\n", v); 382cabdff1aSopenharmony_ci goto skip; 383cabdff1aSopenharmony_ci } 384cabdff1aSopenharmony_ci st->codecpar->codec_tag = avio_rl32(pb); 385cabdff1aSopenharmony_ci st->codecpar->codec_id = ff_codec_get_id(ff_rm_codec_tags, 386cabdff1aSopenharmony_ci st->codecpar->codec_tag); 387cabdff1aSopenharmony_ci av_log(s, AV_LOG_TRACE, "%"PRIX32" %X\n", 388cabdff1aSopenharmony_ci st->codecpar->codec_tag, MKTAG('R', 'V', '2', '0')); 389cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_NONE) 390cabdff1aSopenharmony_ci goto fail1; 391cabdff1aSopenharmony_ci st->codecpar->width = avio_rb16(pb); 392cabdff1aSopenharmony_ci st->codecpar->height = avio_rb16(pb); 393cabdff1aSopenharmony_ci avio_skip(pb, 2); // looks like bits per sample 394cabdff1aSopenharmony_ci avio_skip(pb, 4); // always zero? 395cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 396cabdff1aSopenharmony_ci ffstream(st)->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; 397cabdff1aSopenharmony_ci fps = avio_rb32(pb); 398cabdff1aSopenharmony_ci 399cabdff1aSopenharmony_ci if ((ret = rm_read_extradata(s, pb, st->codecpar, codec_data_size - (avio_tell(pb) - codec_pos))) < 0) 400cabdff1aSopenharmony_ci return ret; 401cabdff1aSopenharmony_ci 402cabdff1aSopenharmony_ci if (fps > 0) { 403cabdff1aSopenharmony_ci av_reduce(&st->avg_frame_rate.den, &st->avg_frame_rate.num, 404cabdff1aSopenharmony_ci 0x10000, fps, (1 << 30) - 1); 405cabdff1aSopenharmony_ci#if FF_API_R_FRAME_RATE 406cabdff1aSopenharmony_ci st->r_frame_rate = st->avg_frame_rate; 407cabdff1aSopenharmony_ci#endif 408cabdff1aSopenharmony_ci } else if (s->error_recognition & AV_EF_EXPLODE) { 409cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Invalid framerate\n"); 410cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 411cabdff1aSopenharmony_ci } 412cabdff1aSopenharmony_ci } 413cabdff1aSopenharmony_ci 414cabdff1aSopenharmony_ciskip: 415cabdff1aSopenharmony_ci /* skip codec info */ 416cabdff1aSopenharmony_ci size = avio_tell(pb) - codec_pos; 417cabdff1aSopenharmony_ci if (codec_data_size >= size) { 418cabdff1aSopenharmony_ci avio_skip(pb, codec_data_size - size); 419cabdff1aSopenharmony_ci } else { 420cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "codec_data_size %u < size %d\n", codec_data_size, size); 421cabdff1aSopenharmony_ci } 422cabdff1aSopenharmony_ci 423cabdff1aSopenharmony_ci return 0; 424cabdff1aSopenharmony_ci} 425cabdff1aSopenharmony_ci 426cabdff1aSopenharmony_ci/** this function assumes that the demuxer has already seeked to the start 427cabdff1aSopenharmony_ci * of the INDX chunk, and will bail out if not. */ 428cabdff1aSopenharmony_cistatic int rm_read_index(AVFormatContext *s) 429cabdff1aSopenharmony_ci{ 430cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 431cabdff1aSopenharmony_ci unsigned int size, n_pkts, str_id, next_off, n, pos, pts; 432cabdff1aSopenharmony_ci AVStream *st; 433cabdff1aSopenharmony_ci 434cabdff1aSopenharmony_ci do { 435cabdff1aSopenharmony_ci if (avio_rl32(pb) != MKTAG('I','N','D','X')) 436cabdff1aSopenharmony_ci return -1; 437cabdff1aSopenharmony_ci size = avio_rb32(pb); 438cabdff1aSopenharmony_ci if (size < 20) 439cabdff1aSopenharmony_ci return -1; 440cabdff1aSopenharmony_ci avio_skip(pb, 2); 441cabdff1aSopenharmony_ci n_pkts = avio_rb32(pb); 442cabdff1aSopenharmony_ci str_id = avio_rb16(pb); 443cabdff1aSopenharmony_ci next_off = avio_rb32(pb); 444cabdff1aSopenharmony_ci for (n = 0; n < s->nb_streams; n++) 445cabdff1aSopenharmony_ci if (s->streams[n]->id == str_id) { 446cabdff1aSopenharmony_ci st = s->streams[n]; 447cabdff1aSopenharmony_ci break; 448cabdff1aSopenharmony_ci } 449cabdff1aSopenharmony_ci if (n == s->nb_streams) { 450cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 451cabdff1aSopenharmony_ci "Invalid stream index %d for index at pos %"PRId64"\n", 452cabdff1aSopenharmony_ci str_id, avio_tell(pb)); 453cabdff1aSopenharmony_ci goto skip; 454cabdff1aSopenharmony_ci } else if ((avio_size(pb) - avio_tell(pb)) / 14 < n_pkts) { 455cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 456cabdff1aSopenharmony_ci "Nr. of packets in packet index for stream index %d " 457cabdff1aSopenharmony_ci "exceeds filesize (%"PRId64" at %"PRId64" = %"PRId64")\n", 458cabdff1aSopenharmony_ci str_id, avio_size(pb), avio_tell(pb), 459cabdff1aSopenharmony_ci (avio_size(pb) - avio_tell(pb)) / 14); 460cabdff1aSopenharmony_ci goto skip; 461cabdff1aSopenharmony_ci } 462cabdff1aSopenharmony_ci 463cabdff1aSopenharmony_ci for (n = 0; n < n_pkts; n++) { 464cabdff1aSopenharmony_ci if (avio_feof(pb)) 465cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 466cabdff1aSopenharmony_ci avio_skip(pb, 2); 467cabdff1aSopenharmony_ci pts = avio_rb32(pb); 468cabdff1aSopenharmony_ci pos = avio_rb32(pb); 469cabdff1aSopenharmony_ci avio_skip(pb, 4); /* packet no. */ 470cabdff1aSopenharmony_ci 471cabdff1aSopenharmony_ci av_add_index_entry(st, pos, pts, 0, 0, AVINDEX_KEYFRAME); 472cabdff1aSopenharmony_ci } 473cabdff1aSopenharmony_ci 474cabdff1aSopenharmony_ciskip: 475cabdff1aSopenharmony_ci if (next_off && avio_tell(pb) < next_off && 476cabdff1aSopenharmony_ci avio_seek(pb, next_off, SEEK_SET) < 0) { 477cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, 478cabdff1aSopenharmony_ci "Non-linear index detected, not supported\n"); 479cabdff1aSopenharmony_ci return -1; 480cabdff1aSopenharmony_ci } 481cabdff1aSopenharmony_ci } while (next_off); 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_ci return 0; 484cabdff1aSopenharmony_ci} 485cabdff1aSopenharmony_ci 486cabdff1aSopenharmony_cistatic int rm_read_header_old(AVFormatContext *s) 487cabdff1aSopenharmony_ci{ 488cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 489cabdff1aSopenharmony_ci AVStream *st; 490cabdff1aSopenharmony_ci 491cabdff1aSopenharmony_ci rm->old_format = 1; 492cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 493cabdff1aSopenharmony_ci if (!st) 494cabdff1aSopenharmony_ci return -1; 495cabdff1aSopenharmony_ci st->priv_data = ff_rm_alloc_rmstream(); 496cabdff1aSopenharmony_ci if (!st->priv_data) 497cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 498cabdff1aSopenharmony_ci return rm_read_audio_stream_info(s, s->pb, st, st->priv_data, 1); 499cabdff1aSopenharmony_ci} 500cabdff1aSopenharmony_ci 501cabdff1aSopenharmony_cistatic int rm_read_multi(AVFormatContext *s, AVIOContext *pb, 502cabdff1aSopenharmony_ci AVStream *st, char *mime) 503cabdff1aSopenharmony_ci{ 504cabdff1aSopenharmony_ci int number_of_streams = avio_rb16(pb); 505cabdff1aSopenharmony_ci int number_of_mdpr; 506cabdff1aSopenharmony_ci int i, ret; 507cabdff1aSopenharmony_ci unsigned size2; 508cabdff1aSopenharmony_ci for (i = 0; i<number_of_streams; i++) 509cabdff1aSopenharmony_ci avio_rb16(pb); 510cabdff1aSopenharmony_ci number_of_mdpr = avio_rb16(pb); 511cabdff1aSopenharmony_ci if (number_of_mdpr != 1) { 512cabdff1aSopenharmony_ci avpriv_request_sample(s, "MLTI with multiple (%d) MDPR", number_of_mdpr); 513cabdff1aSopenharmony_ci } 514cabdff1aSopenharmony_ci for (i = 0; i < number_of_mdpr; i++) { 515cabdff1aSopenharmony_ci AVStream *st2; 516cabdff1aSopenharmony_ci if (i > 0) { 517cabdff1aSopenharmony_ci st2 = avformat_new_stream(s, NULL); 518cabdff1aSopenharmony_ci if (!st2) { 519cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 520cabdff1aSopenharmony_ci return ret; 521cabdff1aSopenharmony_ci } 522cabdff1aSopenharmony_ci st2->id = st->id + (i<<16); 523cabdff1aSopenharmony_ci st2->codecpar->bit_rate = st->codecpar->bit_rate; 524cabdff1aSopenharmony_ci st2->start_time = st->start_time; 525cabdff1aSopenharmony_ci st2->duration = st->duration; 526cabdff1aSopenharmony_ci st2->codecpar->codec_type = AVMEDIA_TYPE_DATA; 527cabdff1aSopenharmony_ci st2->priv_data = ff_rm_alloc_rmstream(); 528cabdff1aSopenharmony_ci if (!st2->priv_data) 529cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 530cabdff1aSopenharmony_ci } else 531cabdff1aSopenharmony_ci st2 = st; 532cabdff1aSopenharmony_ci 533cabdff1aSopenharmony_ci size2 = avio_rb32(pb); 534cabdff1aSopenharmony_ci ret = ff_rm_read_mdpr_codecdata(s, s->pb, st2, st2->priv_data, 535cabdff1aSopenharmony_ci size2, NULL); 536cabdff1aSopenharmony_ci if (ret < 0) 537cabdff1aSopenharmony_ci return ret; 538cabdff1aSopenharmony_ci } 539cabdff1aSopenharmony_ci return 0; 540cabdff1aSopenharmony_ci} 541cabdff1aSopenharmony_ci 542cabdff1aSopenharmony_cistatic int rm_read_header(AVFormatContext *s) 543cabdff1aSopenharmony_ci{ 544cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 545cabdff1aSopenharmony_ci AVStream *st; 546cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 547cabdff1aSopenharmony_ci unsigned int tag; 548cabdff1aSopenharmony_ci int tag_size; 549cabdff1aSopenharmony_ci unsigned int start_time, duration; 550cabdff1aSopenharmony_ci unsigned int data_off = 0, indx_off = 0; 551cabdff1aSopenharmony_ci char buf[128], mime[128]; 552cabdff1aSopenharmony_ci int flags = 0; 553cabdff1aSopenharmony_ci int ret; 554cabdff1aSopenharmony_ci unsigned size, v; 555cabdff1aSopenharmony_ci int64_t codec_pos; 556cabdff1aSopenharmony_ci 557cabdff1aSopenharmony_ci tag = avio_rl32(pb); 558cabdff1aSopenharmony_ci if (tag == MKTAG('.', 'r', 'a', 0xfd)) { 559cabdff1aSopenharmony_ci /* very old .ra format */ 560cabdff1aSopenharmony_ci return rm_read_header_old(s); 561cabdff1aSopenharmony_ci } else if (tag != MKTAG('.', 'R', 'M', 'F')) { 562cabdff1aSopenharmony_ci return AVERROR(EIO); 563cabdff1aSopenharmony_ci } 564cabdff1aSopenharmony_ci 565cabdff1aSopenharmony_ci tag_size = avio_rb32(pb); 566cabdff1aSopenharmony_ci if (tag_size < 0) 567cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 568cabdff1aSopenharmony_ci avio_skip(pb, tag_size - 8); 569cabdff1aSopenharmony_ci 570cabdff1aSopenharmony_ci for(;;) { 571cabdff1aSopenharmony_ci if (avio_feof(pb)) 572cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 573cabdff1aSopenharmony_ci tag = avio_rl32(pb); 574cabdff1aSopenharmony_ci tag_size = avio_rb32(pb); 575cabdff1aSopenharmony_ci avio_rb16(pb); 576cabdff1aSopenharmony_ci av_log(s, AV_LOG_TRACE, "tag=%s size=%d\n", 577cabdff1aSopenharmony_ci av_fourcc2str(tag), tag_size); 578cabdff1aSopenharmony_ci if (tag_size < 10 && tag != MKTAG('D', 'A', 'T', 'A')) 579cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 580cabdff1aSopenharmony_ci switch(tag) { 581cabdff1aSopenharmony_ci case MKTAG('P', 'R', 'O', 'P'): 582cabdff1aSopenharmony_ci /* file header */ 583cabdff1aSopenharmony_ci avio_rb32(pb); /* max bit rate */ 584cabdff1aSopenharmony_ci avio_rb32(pb); /* avg bit rate */ 585cabdff1aSopenharmony_ci avio_rb32(pb); /* max packet size */ 586cabdff1aSopenharmony_ci avio_rb32(pb); /* avg packet size */ 587cabdff1aSopenharmony_ci avio_rb32(pb); /* nb packets */ 588cabdff1aSopenharmony_ci duration = avio_rb32(pb); /* duration */ 589cabdff1aSopenharmony_ci s->duration = av_rescale(duration, AV_TIME_BASE, 1000); 590cabdff1aSopenharmony_ci avio_rb32(pb); /* preroll */ 591cabdff1aSopenharmony_ci indx_off = avio_rb32(pb); /* index offset */ 592cabdff1aSopenharmony_ci data_off = avio_rb32(pb); /* data offset */ 593cabdff1aSopenharmony_ci avio_rb16(pb); /* nb streams */ 594cabdff1aSopenharmony_ci flags = avio_rb16(pb); /* flags */ 595cabdff1aSopenharmony_ci break; 596cabdff1aSopenharmony_ci case MKTAG('C', 'O', 'N', 'T'): 597cabdff1aSopenharmony_ci rm_read_metadata(s, pb, 1); 598cabdff1aSopenharmony_ci break; 599cabdff1aSopenharmony_ci case MKTAG('M', 'D', 'P', 'R'): 600cabdff1aSopenharmony_ci st = avformat_new_stream(s, NULL); 601cabdff1aSopenharmony_ci if (!st) 602cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 603cabdff1aSopenharmony_ci st->id = avio_rb16(pb); 604cabdff1aSopenharmony_ci avio_rb32(pb); /* max bit rate */ 605cabdff1aSopenharmony_ci st->codecpar->bit_rate = avio_rb32(pb); /* bit rate */ 606cabdff1aSopenharmony_ci avio_rb32(pb); /* max packet size */ 607cabdff1aSopenharmony_ci avio_rb32(pb); /* avg packet size */ 608cabdff1aSopenharmony_ci start_time = avio_rb32(pb); /* start time */ 609cabdff1aSopenharmony_ci avio_rb32(pb); /* preroll */ 610cabdff1aSopenharmony_ci duration = avio_rb32(pb); /* duration */ 611cabdff1aSopenharmony_ci st->start_time = start_time; 612cabdff1aSopenharmony_ci st->duration = duration; 613cabdff1aSopenharmony_ci if(duration>0) 614cabdff1aSopenharmony_ci s->duration = AV_NOPTS_VALUE; 615cabdff1aSopenharmony_ci get_str8(pb, buf, sizeof(buf)); /* desc */ 616cabdff1aSopenharmony_ci get_str8(pb, mime, sizeof(mime)); /* mimetype */ 617cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_DATA; 618cabdff1aSopenharmony_ci st->priv_data = ff_rm_alloc_rmstream(); 619cabdff1aSopenharmony_ci if (!st->priv_data) 620cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 621cabdff1aSopenharmony_ci 622cabdff1aSopenharmony_ci size = avio_rb32(pb); 623cabdff1aSopenharmony_ci codec_pos = avio_tell(pb); 624cabdff1aSopenharmony_ci 625cabdff1aSopenharmony_ci ffio_ensure_seekback(pb, 4); 626cabdff1aSopenharmony_ci v = avio_rb32(pb); 627cabdff1aSopenharmony_ci if (v == MKBETAG('M', 'L', 'T', 'I')) { 628cabdff1aSopenharmony_ci ret = rm_read_multi(s, s->pb, st, mime); 629cabdff1aSopenharmony_ci if (ret < 0) 630cabdff1aSopenharmony_ci return ret; 631cabdff1aSopenharmony_ci avio_seek(pb, codec_pos + size, SEEK_SET); 632cabdff1aSopenharmony_ci } else { 633cabdff1aSopenharmony_ci avio_skip(pb, -4); 634cabdff1aSopenharmony_ci ret = ff_rm_read_mdpr_codecdata(s, s->pb, st, st->priv_data, 635cabdff1aSopenharmony_ci size, mime); 636cabdff1aSopenharmony_ci if (ret < 0) 637cabdff1aSopenharmony_ci return ret; 638cabdff1aSopenharmony_ci } 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci break; 641cabdff1aSopenharmony_ci case MKTAG('D', 'A', 'T', 'A'): 642cabdff1aSopenharmony_ci goto header_end; 643cabdff1aSopenharmony_ci default: 644cabdff1aSopenharmony_ci /* unknown tag: skip it */ 645cabdff1aSopenharmony_ci avio_skip(pb, tag_size - 10); 646cabdff1aSopenharmony_ci break; 647cabdff1aSopenharmony_ci } 648cabdff1aSopenharmony_ci } 649cabdff1aSopenharmony_ci header_end: 650cabdff1aSopenharmony_ci rm->nb_packets = avio_rb32(pb); /* number of packets */ 651cabdff1aSopenharmony_ci if (!rm->nb_packets && (flags & 4)) 652cabdff1aSopenharmony_ci rm->nb_packets = 3600 * 25; 653cabdff1aSopenharmony_ci avio_rb32(pb); /* next data header */ 654cabdff1aSopenharmony_ci 655cabdff1aSopenharmony_ci if (!data_off) 656cabdff1aSopenharmony_ci data_off = avio_tell(pb) - 18; 657cabdff1aSopenharmony_ci if (indx_off && (pb->seekable & AVIO_SEEKABLE_NORMAL) && 658cabdff1aSopenharmony_ci !(s->flags & AVFMT_FLAG_IGNIDX) && 659cabdff1aSopenharmony_ci avio_seek(pb, indx_off, SEEK_SET) >= 0) { 660cabdff1aSopenharmony_ci rm_read_index(s); 661cabdff1aSopenharmony_ci avio_seek(pb, data_off + 18, SEEK_SET); 662cabdff1aSopenharmony_ci } 663cabdff1aSopenharmony_ci 664cabdff1aSopenharmony_ci return 0; 665cabdff1aSopenharmony_ci} 666cabdff1aSopenharmony_ci 667cabdff1aSopenharmony_cistatic int get_num(AVIOContext *pb, int *len) 668cabdff1aSopenharmony_ci{ 669cabdff1aSopenharmony_ci int n, n1; 670cabdff1aSopenharmony_ci 671cabdff1aSopenharmony_ci n = avio_rb16(pb); 672cabdff1aSopenharmony_ci (*len)-=2; 673cabdff1aSopenharmony_ci n &= 0x7FFF; 674cabdff1aSopenharmony_ci if (n >= 0x4000) { 675cabdff1aSopenharmony_ci return n - 0x4000; 676cabdff1aSopenharmony_ci } else { 677cabdff1aSopenharmony_ci n1 = avio_rb16(pb); 678cabdff1aSopenharmony_ci (*len)-=2; 679cabdff1aSopenharmony_ci return (n << 16) | n1; 680cabdff1aSopenharmony_ci } 681cabdff1aSopenharmony_ci} 682cabdff1aSopenharmony_ci 683cabdff1aSopenharmony_ci/* multiple of 20 bytes for ra144 (ugly) */ 684cabdff1aSopenharmony_ci#define RAW_PACKET_SIZE 1000 685cabdff1aSopenharmony_ci 686cabdff1aSopenharmony_cistatic int rm_sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){ 687cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 688cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 689cabdff1aSopenharmony_ci AVStream *st; 690cabdff1aSopenharmony_ci uint32_t state=0xFFFFFFFF; 691cabdff1aSopenharmony_ci 692cabdff1aSopenharmony_ci while(!avio_feof(pb)){ 693cabdff1aSopenharmony_ci int len, num, i; 694cabdff1aSopenharmony_ci int mlti_id; 695cabdff1aSopenharmony_ci *pos= avio_tell(pb) - 3; 696cabdff1aSopenharmony_ci if(rm->remaining_len > 0){ 697cabdff1aSopenharmony_ci num= rm->current_stream; 698cabdff1aSopenharmony_ci mlti_id = 0; 699cabdff1aSopenharmony_ci len= rm->remaining_len; 700cabdff1aSopenharmony_ci *timestamp = AV_NOPTS_VALUE; 701cabdff1aSopenharmony_ci *flags= 0; 702cabdff1aSopenharmony_ci }else{ 703cabdff1aSopenharmony_ci state= (state<<8) + avio_r8(pb); 704cabdff1aSopenharmony_ci 705cabdff1aSopenharmony_ci if(state == MKBETAG('I', 'N', 'D', 'X')){ 706cabdff1aSopenharmony_ci int n_pkts; 707cabdff1aSopenharmony_ci int64_t expected_len; 708cabdff1aSopenharmony_ci len = avio_rb32(pb); 709cabdff1aSopenharmony_ci avio_skip(pb, 2); 710cabdff1aSopenharmony_ci n_pkts = avio_rb32(pb); 711cabdff1aSopenharmony_ci expected_len = 20 + n_pkts * 14LL; 712cabdff1aSopenharmony_ci 713cabdff1aSopenharmony_ci if (len == 20 && expected_len <= INT_MAX) 714cabdff1aSopenharmony_ci /* some files don't add index entries to chunk size... */ 715cabdff1aSopenharmony_ci len = expected_len; 716cabdff1aSopenharmony_ci else if (len != expected_len) 717cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 718cabdff1aSopenharmony_ci "Index size %d (%d pkts) is wrong, should be %"PRId64".\n", 719cabdff1aSopenharmony_ci len, n_pkts, expected_len); 720cabdff1aSopenharmony_ci if(len < 14) 721cabdff1aSopenharmony_ci continue; 722cabdff1aSopenharmony_ci len -= 14; // we already read part of the index header 723cabdff1aSopenharmony_ci goto skip; 724cabdff1aSopenharmony_ci } else if (state == MKBETAG('D','A','T','A')) { 725cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, 726cabdff1aSopenharmony_ci "DATA tag in middle of chunk, file may be broken.\n"); 727cabdff1aSopenharmony_ci } 728cabdff1aSopenharmony_ci 729cabdff1aSopenharmony_ci if(state > (unsigned)0xFFFF || state <= 12) 730cabdff1aSopenharmony_ci continue; 731cabdff1aSopenharmony_ci len=state - 12; 732cabdff1aSopenharmony_ci state= 0xFFFFFFFF; 733cabdff1aSopenharmony_ci 734cabdff1aSopenharmony_ci num = avio_rb16(pb); 735cabdff1aSopenharmony_ci *timestamp = avio_rb32(pb); 736cabdff1aSopenharmony_ci mlti_id = (avio_r8(pb) >> 1) - 1; 737cabdff1aSopenharmony_ci mlti_id = FFMAX(mlti_id, 0) << 16; 738cabdff1aSopenharmony_ci *flags = avio_r8(pb); /* flags */ 739cabdff1aSopenharmony_ci } 740cabdff1aSopenharmony_ci for(i=0;i<s->nb_streams;i++) { 741cabdff1aSopenharmony_ci st = s->streams[i]; 742cabdff1aSopenharmony_ci if (mlti_id + num == st->id) 743cabdff1aSopenharmony_ci break; 744cabdff1aSopenharmony_ci } 745cabdff1aSopenharmony_ci if (i == s->nb_streams) { 746cabdff1aSopenharmony_ciskip: 747cabdff1aSopenharmony_ci /* skip packet if unknown number */ 748cabdff1aSopenharmony_ci avio_skip(pb, len); 749cabdff1aSopenharmony_ci rm->remaining_len = 0; 750cabdff1aSopenharmony_ci continue; 751cabdff1aSopenharmony_ci } 752cabdff1aSopenharmony_ci *stream_index= i; 753cabdff1aSopenharmony_ci 754cabdff1aSopenharmony_ci return len; 755cabdff1aSopenharmony_ci } 756cabdff1aSopenharmony_ci return -1; 757cabdff1aSopenharmony_ci} 758cabdff1aSopenharmony_ci 759cabdff1aSopenharmony_cistatic int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, 760cabdff1aSopenharmony_ci RMDemuxContext *rm, RMStream *vst, 761cabdff1aSopenharmony_ci AVPacket *pkt, int len, int *pseq, 762cabdff1aSopenharmony_ci int64_t *timestamp) 763cabdff1aSopenharmony_ci{ 764cabdff1aSopenharmony_ci int hdr; 765cabdff1aSopenharmony_ci int seq = 0, pic_num = 0, len2 = 0, pos = 0; //init to silence compiler warning 766cabdff1aSopenharmony_ci int type; 767cabdff1aSopenharmony_ci int ret; 768cabdff1aSopenharmony_ci 769cabdff1aSopenharmony_ci hdr = avio_r8(pb); len--; 770cabdff1aSopenharmony_ci type = hdr >> 6; 771cabdff1aSopenharmony_ci 772cabdff1aSopenharmony_ci if(type != 3){ // not frame as a part of packet 773cabdff1aSopenharmony_ci seq = avio_r8(pb); len--; 774cabdff1aSopenharmony_ci } 775cabdff1aSopenharmony_ci if(type != 1){ // not whole frame 776cabdff1aSopenharmony_ci len2 = get_num(pb, &len); 777cabdff1aSopenharmony_ci pos = get_num(pb, &len); 778cabdff1aSopenharmony_ci pic_num = avio_r8(pb); len--; 779cabdff1aSopenharmony_ci } 780cabdff1aSopenharmony_ci if(len<0) { 781cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Insufficient data\n"); 782cabdff1aSopenharmony_ci return -1; 783cabdff1aSopenharmony_ci } 784cabdff1aSopenharmony_ci rm->remaining_len = len; 785cabdff1aSopenharmony_ci if(type&1){ // frame, not slice 786cabdff1aSopenharmony_ci if(type == 3){ // frame as a part of packet 787cabdff1aSopenharmony_ci len= len2; 788cabdff1aSopenharmony_ci *timestamp = pos; 789cabdff1aSopenharmony_ci } 790cabdff1aSopenharmony_ci if(rm->remaining_len < len) { 791cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Insufficient remaining len\n"); 792cabdff1aSopenharmony_ci return -1; 793cabdff1aSopenharmony_ci } 794cabdff1aSopenharmony_ci rm->remaining_len -= len; 795cabdff1aSopenharmony_ci if ((ret = av_new_packet(pkt, len + 9)) < 0) 796cabdff1aSopenharmony_ci return ret; 797cabdff1aSopenharmony_ci pkt->data[0] = 0; 798cabdff1aSopenharmony_ci AV_WL32(pkt->data + 1, 1); 799cabdff1aSopenharmony_ci AV_WL32(pkt->data + 5, 0); 800cabdff1aSopenharmony_ci if ((ret = avio_read(pb, pkt->data + 9, len)) != len) { 801cabdff1aSopenharmony_ci av_packet_unref(pkt); 802cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Failed to read %d bytes\n", len); 803cabdff1aSopenharmony_ci return ret < 0 ? ret : AVERROR(EIO); 804cabdff1aSopenharmony_ci } 805cabdff1aSopenharmony_ci return 0; 806cabdff1aSopenharmony_ci } 807cabdff1aSopenharmony_ci //now we have to deal with single slice 808cabdff1aSopenharmony_ci 809cabdff1aSopenharmony_ci *pseq = seq; 810cabdff1aSopenharmony_ci if((seq & 0x7F) == 1 || vst->curpic_num != pic_num){ 811cabdff1aSopenharmony_ci if (len2 > ffio_limit(pb, len2)) { 812cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Impossibly sized packet\n"); 813cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 814cabdff1aSopenharmony_ci } 815cabdff1aSopenharmony_ci vst->slices = ((hdr & 0x3F) << 1) + 1; 816cabdff1aSopenharmony_ci vst->videobufsize = len2 + 8*vst->slices + 1; 817cabdff1aSopenharmony_ci av_packet_unref(&vst->pkt); //FIXME this should be output. 818cabdff1aSopenharmony_ci if ((ret = av_new_packet(&vst->pkt, vst->videobufsize)) < 0) 819cabdff1aSopenharmony_ci return ret; 820cabdff1aSopenharmony_ci vst->videobufpos = 8*vst->slices + 1; 821cabdff1aSopenharmony_ci vst->cur_slice = 0; 822cabdff1aSopenharmony_ci vst->curpic_num = pic_num; 823cabdff1aSopenharmony_ci vst->pktpos = avio_tell(pb); 824cabdff1aSopenharmony_ci } 825cabdff1aSopenharmony_ci if(type == 2) 826cabdff1aSopenharmony_ci len = FFMIN(len, pos); 827cabdff1aSopenharmony_ci 828cabdff1aSopenharmony_ci if(++vst->cur_slice > vst->slices) { 829cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "cur slice %d, too large\n", vst->cur_slice); 830cabdff1aSopenharmony_ci return 1; 831cabdff1aSopenharmony_ci } 832cabdff1aSopenharmony_ci if(!vst->pkt.data) 833cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 834cabdff1aSopenharmony_ci AV_WL32(vst->pkt.data - 7 + 8*vst->cur_slice, 1); 835cabdff1aSopenharmony_ci AV_WL32(vst->pkt.data - 3 + 8*vst->cur_slice, vst->videobufpos - 8*vst->slices - 1); 836cabdff1aSopenharmony_ci if(vst->videobufpos + len > vst->videobufsize) { 837cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "outside videobufsize\n"); 838cabdff1aSopenharmony_ci return 1; 839cabdff1aSopenharmony_ci } 840cabdff1aSopenharmony_ci if (avio_read(pb, vst->pkt.data + vst->videobufpos, len) != len) 841cabdff1aSopenharmony_ci return AVERROR(EIO); 842cabdff1aSopenharmony_ci vst->videobufpos += len; 843cabdff1aSopenharmony_ci rm->remaining_len-= len; 844cabdff1aSopenharmony_ci 845cabdff1aSopenharmony_ci if (type == 2 || vst->videobufpos == vst->videobufsize) { 846cabdff1aSopenharmony_ci vst->pkt.data[0] = vst->cur_slice-1; 847cabdff1aSopenharmony_ci av_packet_move_ref(pkt, &vst->pkt); 848cabdff1aSopenharmony_ci if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin 849cabdff1aSopenharmony_ci memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices, 850cabdff1aSopenharmony_ci vst->videobufpos - 1 - 8*vst->slices); 851cabdff1aSopenharmony_ci av_shrink_packet(pkt, vst->videobufpos + 8*(vst->cur_slice - vst->slices)); 852cabdff1aSopenharmony_ci pkt->pts = AV_NOPTS_VALUE; 853cabdff1aSopenharmony_ci pkt->pos = vst->pktpos; 854cabdff1aSopenharmony_ci vst->slices = 0; 855cabdff1aSopenharmony_ci return 0; 856cabdff1aSopenharmony_ci } 857cabdff1aSopenharmony_ci 858cabdff1aSopenharmony_ci return 1; 859cabdff1aSopenharmony_ci} 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_cistatic inline void 862cabdff1aSopenharmony_cirm_ac3_swap_bytes (AVStream *st, AVPacket *pkt) 863cabdff1aSopenharmony_ci{ 864cabdff1aSopenharmony_ci uint8_t *ptr; 865cabdff1aSopenharmony_ci int j; 866cabdff1aSopenharmony_ci 867cabdff1aSopenharmony_ci if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { 868cabdff1aSopenharmony_ci ptr = pkt->data; 869cabdff1aSopenharmony_ci for (j=0;j<pkt->size;j+=2) { 870cabdff1aSopenharmony_ci FFSWAP(int, ptr[0], ptr[1]); 871cabdff1aSopenharmony_ci ptr += 2; 872cabdff1aSopenharmony_ci } 873cabdff1aSopenharmony_ci } 874cabdff1aSopenharmony_ci} 875cabdff1aSopenharmony_ci 876cabdff1aSopenharmony_cistatic int readfull(AVFormatContext *s, AVIOContext *pb, uint8_t *dst, int n) { 877cabdff1aSopenharmony_ci int ret = avio_read(pb, dst, n); 878cabdff1aSopenharmony_ci if (ret != n) { 879cabdff1aSopenharmony_ci if (ret >= 0) memset(dst + ret, 0, n - ret); 880cabdff1aSopenharmony_ci else memset(dst , 0, n); 881cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Failed to fully read block\n"); 882cabdff1aSopenharmony_ci } 883cabdff1aSopenharmony_ci return ret; 884cabdff1aSopenharmony_ci} 885cabdff1aSopenharmony_ci 886cabdff1aSopenharmony_ciint 887cabdff1aSopenharmony_ciff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, 888cabdff1aSopenharmony_ci AVStream *st, RMStream *ast, int len, AVPacket *pkt, 889cabdff1aSopenharmony_ci int *seq, int flags, int64_t timestamp) 890cabdff1aSopenharmony_ci{ 891cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 892cabdff1aSopenharmony_ci int ret; 893cabdff1aSopenharmony_ci 894cabdff1aSopenharmony_ci if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { 895cabdff1aSopenharmony_ci rm->current_stream= st->id; 896cabdff1aSopenharmony_ci ret = rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, ×tamp); 897cabdff1aSopenharmony_ci if(ret) 898cabdff1aSopenharmony_ci return ret < 0 ? ret : -1; //got partial frame or error 899cabdff1aSopenharmony_ci } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { 900cabdff1aSopenharmony_ci if ((ast->deint_id == DEINT_ID_GENR) || 901cabdff1aSopenharmony_ci (ast->deint_id == DEINT_ID_INT4) || 902cabdff1aSopenharmony_ci (ast->deint_id == DEINT_ID_SIPR)) { 903cabdff1aSopenharmony_ci int x; 904cabdff1aSopenharmony_ci int sps = ast->sub_packet_size; 905cabdff1aSopenharmony_ci int cfs = ast->coded_framesize; 906cabdff1aSopenharmony_ci int h = ast->sub_packet_h; 907cabdff1aSopenharmony_ci int y = ast->sub_packet_cnt; 908cabdff1aSopenharmony_ci int w = ast->audio_framesize; 909cabdff1aSopenharmony_ci 910cabdff1aSopenharmony_ci if (flags & 2) 911cabdff1aSopenharmony_ci y = ast->sub_packet_cnt = 0; 912cabdff1aSopenharmony_ci if (!y) 913cabdff1aSopenharmony_ci ast->audiotimestamp = timestamp; 914cabdff1aSopenharmony_ci 915cabdff1aSopenharmony_ci switch (ast->deint_id) { 916cabdff1aSopenharmony_ci case DEINT_ID_INT4: 917cabdff1aSopenharmony_ci for (x = 0; x < h/2; x++) 918cabdff1aSopenharmony_ci readfull(s, pb, ast->pkt.data+x*2*w+y*cfs, cfs); 919cabdff1aSopenharmony_ci break; 920cabdff1aSopenharmony_ci case DEINT_ID_GENR: 921cabdff1aSopenharmony_ci for (x = 0; x < w/sps; x++) 922cabdff1aSopenharmony_ci readfull(s, pb, ast->pkt.data+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), sps); 923cabdff1aSopenharmony_ci break; 924cabdff1aSopenharmony_ci case DEINT_ID_SIPR: 925cabdff1aSopenharmony_ci readfull(s, pb, ast->pkt.data + y * w, w); 926cabdff1aSopenharmony_ci break; 927cabdff1aSopenharmony_ci } 928cabdff1aSopenharmony_ci 929cabdff1aSopenharmony_ci if (++(ast->sub_packet_cnt) < h) 930cabdff1aSopenharmony_ci return -1; 931cabdff1aSopenharmony_ci if (ast->deint_id == DEINT_ID_SIPR) 932cabdff1aSopenharmony_ci ff_rm_reorder_sipr_data(ast->pkt.data, h, w); 933cabdff1aSopenharmony_ci 934cabdff1aSopenharmony_ci ast->sub_packet_cnt = 0; 935cabdff1aSopenharmony_ci rm->audio_stream_num = st->index; 936cabdff1aSopenharmony_ci if (st->codecpar->block_align <= 0) { 937cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Invalid block alignment %d\n", st->codecpar->block_align); 938cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 939cabdff1aSopenharmony_ci } 940cabdff1aSopenharmony_ci rm->audio_pkt_cnt = h * w / st->codecpar->block_align; 941cabdff1aSopenharmony_ci } else if ((ast->deint_id == DEINT_ID_VBRF) || 942cabdff1aSopenharmony_ci (ast->deint_id == DEINT_ID_VBRS)) { 943cabdff1aSopenharmony_ci int x; 944cabdff1aSopenharmony_ci rm->audio_stream_num = st->index; 945cabdff1aSopenharmony_ci ast->sub_packet_cnt = (avio_rb16(pb) & 0xf0) >> 4; 946cabdff1aSopenharmony_ci if (ast->sub_packet_cnt) { 947cabdff1aSopenharmony_ci for (x = 0; x < ast->sub_packet_cnt; x++) 948cabdff1aSopenharmony_ci ast->sub_packet_lengths[x] = avio_rb16(pb); 949cabdff1aSopenharmony_ci rm->audio_pkt_cnt = ast->sub_packet_cnt; 950cabdff1aSopenharmony_ci ast->audiotimestamp = timestamp; 951cabdff1aSopenharmony_ci } else 952cabdff1aSopenharmony_ci return -1; 953cabdff1aSopenharmony_ci } else { 954cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, len); 955cabdff1aSopenharmony_ci if (ret < 0) 956cabdff1aSopenharmony_ci return ret; 957cabdff1aSopenharmony_ci rm_ac3_swap_bytes(st, pkt); 958cabdff1aSopenharmony_ci } 959cabdff1aSopenharmony_ci } else { 960cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, len); 961cabdff1aSopenharmony_ci if (ret < 0) 962cabdff1aSopenharmony_ci return ret; 963cabdff1aSopenharmony_ci } 964cabdff1aSopenharmony_ci 965cabdff1aSopenharmony_ci pkt->stream_index = st->index; 966cabdff1aSopenharmony_ci 967cabdff1aSopenharmony_ci pkt->pts = timestamp; 968cabdff1aSopenharmony_ci if (flags & 2) 969cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 970cabdff1aSopenharmony_ci 971cabdff1aSopenharmony_ci return st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? rm->audio_pkt_cnt : 0; 972cabdff1aSopenharmony_ci} 973cabdff1aSopenharmony_ci 974cabdff1aSopenharmony_ciint 975cabdff1aSopenharmony_ciff_rm_retrieve_cache (AVFormatContext *s, AVIOContext *pb, 976cabdff1aSopenharmony_ci AVStream *st, RMStream *ast, AVPacket *pkt) 977cabdff1aSopenharmony_ci{ 978cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 979cabdff1aSopenharmony_ci int ret; 980cabdff1aSopenharmony_ci 981cabdff1aSopenharmony_ci av_assert0 (rm->audio_pkt_cnt > 0); 982cabdff1aSopenharmony_ci 983cabdff1aSopenharmony_ci if (ast->deint_id == DEINT_ID_VBRF || 984cabdff1aSopenharmony_ci ast->deint_id == DEINT_ID_VBRS) { 985cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, ast->sub_packet_lengths[ast->sub_packet_cnt - rm->audio_pkt_cnt]); 986cabdff1aSopenharmony_ci if (ret < 0) 987cabdff1aSopenharmony_ci return ret; 988cabdff1aSopenharmony_ci } else { 989cabdff1aSopenharmony_ci ret = av_new_packet(pkt, st->codecpar->block_align); 990cabdff1aSopenharmony_ci if (ret < 0) 991cabdff1aSopenharmony_ci return ret; 992cabdff1aSopenharmony_ci memcpy(pkt->data, ast->pkt.data + st->codecpar->block_align * //FIXME avoid this 993cabdff1aSopenharmony_ci (ast->sub_packet_h * ast->audio_framesize / st->codecpar->block_align - rm->audio_pkt_cnt), 994cabdff1aSopenharmony_ci st->codecpar->block_align); 995cabdff1aSopenharmony_ci } 996cabdff1aSopenharmony_ci rm->audio_pkt_cnt--; 997cabdff1aSopenharmony_ci if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) { 998cabdff1aSopenharmony_ci ast->audiotimestamp = AV_NOPTS_VALUE; 999cabdff1aSopenharmony_ci pkt->flags = AV_PKT_FLAG_KEY; 1000cabdff1aSopenharmony_ci } else 1001cabdff1aSopenharmony_ci pkt->flags = 0; 1002cabdff1aSopenharmony_ci pkt->stream_index = st->index; 1003cabdff1aSopenharmony_ci 1004cabdff1aSopenharmony_ci return rm->audio_pkt_cnt; 1005cabdff1aSopenharmony_ci} 1006cabdff1aSopenharmony_ci 1007cabdff1aSopenharmony_cistatic int rm_read_packet(AVFormatContext *s, AVPacket *pkt) 1008cabdff1aSopenharmony_ci{ 1009cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 1010cabdff1aSopenharmony_ci AVStream *st = NULL; // init to silence compiler warning 1011cabdff1aSopenharmony_ci int i, res, seq = 1; 1012cabdff1aSopenharmony_ci int64_t timestamp, pos, len; 1013cabdff1aSopenharmony_ci int flags; 1014cabdff1aSopenharmony_ci 1015cabdff1aSopenharmony_ci for (;;) { 1016cabdff1aSopenharmony_ci if (rm->audio_pkt_cnt) { 1017cabdff1aSopenharmony_ci // If there are queued audio packet return them first 1018cabdff1aSopenharmony_ci st = s->streams[rm->audio_stream_num]; 1019cabdff1aSopenharmony_ci res = ff_rm_retrieve_cache(s, s->pb, st, st->priv_data, pkt); 1020cabdff1aSopenharmony_ci if(res < 0) 1021cabdff1aSopenharmony_ci return res; 1022cabdff1aSopenharmony_ci flags = 0; 1023cabdff1aSopenharmony_ci } else { 1024cabdff1aSopenharmony_ci if (rm->old_format) { 1025cabdff1aSopenharmony_ci RMStream *ast; 1026cabdff1aSopenharmony_ci 1027cabdff1aSopenharmony_ci st = s->streams[0]; 1028cabdff1aSopenharmony_ci ast = st->priv_data; 1029cabdff1aSopenharmony_ci timestamp = AV_NOPTS_VALUE; 1030cabdff1aSopenharmony_ci len = !ast->audio_framesize ? RAW_PACKET_SIZE : 1031cabdff1aSopenharmony_ci ast->coded_framesize * (int64_t)ast->sub_packet_h / 2; 1032cabdff1aSopenharmony_ci if (len > INT_MAX) 1033cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1034cabdff1aSopenharmony_ci flags = (seq++ == 1) ? 2 : 0; 1035cabdff1aSopenharmony_ci pos = avio_tell(s->pb); 1036cabdff1aSopenharmony_ci } else { 1037cabdff1aSopenharmony_ci len = rm_sync(s, ×tamp, &flags, &i, &pos); 1038cabdff1aSopenharmony_ci if (len > 0) 1039cabdff1aSopenharmony_ci st = s->streams[i]; 1040cabdff1aSopenharmony_ci } 1041cabdff1aSopenharmony_ci 1042cabdff1aSopenharmony_ci if (avio_feof(s->pb)) 1043cabdff1aSopenharmony_ci return AVERROR_EOF; 1044cabdff1aSopenharmony_ci if (len <= 0) 1045cabdff1aSopenharmony_ci return AVERROR(EIO); 1046cabdff1aSopenharmony_ci 1047cabdff1aSopenharmony_ci res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt, 1048cabdff1aSopenharmony_ci &seq, flags, timestamp); 1049cabdff1aSopenharmony_ci if (res < -1) 1050cabdff1aSopenharmony_ci return res; 1051cabdff1aSopenharmony_ci if((flags&2) && (seq&0x7F) == 1) 1052cabdff1aSopenharmony_ci av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME); 1053cabdff1aSopenharmony_ci if (res) 1054cabdff1aSopenharmony_ci continue; 1055cabdff1aSopenharmony_ci } 1056cabdff1aSopenharmony_ci 1057cabdff1aSopenharmony_ci if( (st->discard >= AVDISCARD_NONKEY && !(flags&2)) 1058cabdff1aSopenharmony_ci || st->discard >= AVDISCARD_ALL){ 1059cabdff1aSopenharmony_ci av_packet_unref(pkt); 1060cabdff1aSopenharmony_ci } else 1061cabdff1aSopenharmony_ci break; 1062cabdff1aSopenharmony_ci } 1063cabdff1aSopenharmony_ci 1064cabdff1aSopenharmony_ci return 0; 1065cabdff1aSopenharmony_ci} 1066cabdff1aSopenharmony_ci 1067cabdff1aSopenharmony_cistatic int rm_read_close(AVFormatContext *s) 1068cabdff1aSopenharmony_ci{ 1069cabdff1aSopenharmony_ci int i; 1070cabdff1aSopenharmony_ci 1071cabdff1aSopenharmony_ci for (i=0;i<s->nb_streams;i++) 1072cabdff1aSopenharmony_ci ff_rm_free_rmstream(s->streams[i]->priv_data); 1073cabdff1aSopenharmony_ci 1074cabdff1aSopenharmony_ci return 0; 1075cabdff1aSopenharmony_ci} 1076cabdff1aSopenharmony_ci 1077cabdff1aSopenharmony_cistatic int rm_probe(const AVProbeData *p) 1078cabdff1aSopenharmony_ci{ 1079cabdff1aSopenharmony_ci /* check file header */ 1080cabdff1aSopenharmony_ci if ((p->buf[0] == '.' && p->buf[1] == 'R' && 1081cabdff1aSopenharmony_ci p->buf[2] == 'M' && p->buf[3] == 'F' && 1082cabdff1aSopenharmony_ci p->buf[4] == 0 && p->buf[5] == 0) || 1083cabdff1aSopenharmony_ci (p->buf[0] == '.' && p->buf[1] == 'r' && 1084cabdff1aSopenharmony_ci p->buf[2] == 'a' && p->buf[3] == 0xfd)) 1085cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 1086cabdff1aSopenharmony_ci else 1087cabdff1aSopenharmony_ci return 0; 1088cabdff1aSopenharmony_ci} 1089cabdff1aSopenharmony_ci 1090cabdff1aSopenharmony_cistatic int64_t rm_read_dts(AVFormatContext *s, int stream_index, 1091cabdff1aSopenharmony_ci int64_t *ppos, int64_t pos_limit) 1092cabdff1aSopenharmony_ci{ 1093cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 1094cabdff1aSopenharmony_ci int64_t pos, dts; 1095cabdff1aSopenharmony_ci int stream_index2, flags, len, h; 1096cabdff1aSopenharmony_ci 1097cabdff1aSopenharmony_ci pos = *ppos; 1098cabdff1aSopenharmony_ci 1099cabdff1aSopenharmony_ci if(rm->old_format) 1100cabdff1aSopenharmony_ci return AV_NOPTS_VALUE; 1101cabdff1aSopenharmony_ci 1102cabdff1aSopenharmony_ci if (avio_seek(s->pb, pos, SEEK_SET) < 0) 1103cabdff1aSopenharmony_ci return AV_NOPTS_VALUE; 1104cabdff1aSopenharmony_ci 1105cabdff1aSopenharmony_ci rm->remaining_len=0; 1106cabdff1aSopenharmony_ci for(;;){ 1107cabdff1aSopenharmony_ci int seq=1; 1108cabdff1aSopenharmony_ci AVStream *st; 1109cabdff1aSopenharmony_ci 1110cabdff1aSopenharmony_ci len = rm_sync(s, &dts, &flags, &stream_index2, &pos); 1111cabdff1aSopenharmony_ci if(len<0) 1112cabdff1aSopenharmony_ci return AV_NOPTS_VALUE; 1113cabdff1aSopenharmony_ci 1114cabdff1aSopenharmony_ci st = s->streams[stream_index2]; 1115cabdff1aSopenharmony_ci if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { 1116cabdff1aSopenharmony_ci h= avio_r8(s->pb); len--; 1117cabdff1aSopenharmony_ci if(!(h & 0x40)){ 1118cabdff1aSopenharmony_ci seq = avio_r8(s->pb); len--; 1119cabdff1aSopenharmony_ci } 1120cabdff1aSopenharmony_ci } 1121cabdff1aSopenharmony_ci 1122cabdff1aSopenharmony_ci if((flags&2) && (seq&0x7F) == 1){ 1123cabdff1aSopenharmony_ci av_log(s, AV_LOG_TRACE, "%d %d-%d %"PRId64" %d\n", 1124cabdff1aSopenharmony_ci flags, stream_index2, stream_index, dts, seq); 1125cabdff1aSopenharmony_ci av_add_index_entry(st, pos, dts, 0, 0, AVINDEX_KEYFRAME); 1126cabdff1aSopenharmony_ci if(stream_index2 == stream_index) 1127cabdff1aSopenharmony_ci break; 1128cabdff1aSopenharmony_ci } 1129cabdff1aSopenharmony_ci 1130cabdff1aSopenharmony_ci avio_skip(s->pb, len); 1131cabdff1aSopenharmony_ci } 1132cabdff1aSopenharmony_ci *ppos = pos; 1133cabdff1aSopenharmony_ci return dts; 1134cabdff1aSopenharmony_ci} 1135cabdff1aSopenharmony_ci 1136cabdff1aSopenharmony_cistatic int rm_read_seek(AVFormatContext *s, int stream_index, 1137cabdff1aSopenharmony_ci int64_t pts, int flags) 1138cabdff1aSopenharmony_ci{ 1139cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 1140cabdff1aSopenharmony_ci 1141cabdff1aSopenharmony_ci if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0) 1142cabdff1aSopenharmony_ci return -1; 1143cabdff1aSopenharmony_ci rm->audio_pkt_cnt = 0; 1144cabdff1aSopenharmony_ci return 0; 1145cabdff1aSopenharmony_ci} 1146cabdff1aSopenharmony_ci 1147cabdff1aSopenharmony_ci 1148cabdff1aSopenharmony_ciconst AVInputFormat ff_rm_demuxer = { 1149cabdff1aSopenharmony_ci .name = "rm", 1150cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("RealMedia"), 1151cabdff1aSopenharmony_ci .priv_data_size = sizeof(RMDemuxContext), 1152cabdff1aSopenharmony_ci .flags_internal = FF_FMT_INIT_CLEANUP, 1153cabdff1aSopenharmony_ci .read_probe = rm_probe, 1154cabdff1aSopenharmony_ci .read_header = rm_read_header, 1155cabdff1aSopenharmony_ci .read_packet = rm_read_packet, 1156cabdff1aSopenharmony_ci .read_close = rm_read_close, 1157cabdff1aSopenharmony_ci .read_timestamp = rm_read_dts, 1158cabdff1aSopenharmony_ci .read_seek = rm_read_seek, 1159cabdff1aSopenharmony_ci}; 1160cabdff1aSopenharmony_ci 1161cabdff1aSopenharmony_ciconst AVInputFormat ff_rdt_demuxer = { 1162cabdff1aSopenharmony_ci .name = "rdt", 1163cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("RDT demuxer"), 1164cabdff1aSopenharmony_ci .priv_data_size = sizeof(RMDemuxContext), 1165cabdff1aSopenharmony_ci .read_close = rm_read_close, 1166cabdff1aSopenharmony_ci .flags = AVFMT_NOFILE, 1167cabdff1aSopenharmony_ci}; 1168cabdff1aSopenharmony_ci 1169cabdff1aSopenharmony_cistatic int ivr_probe(const AVProbeData *p) 1170cabdff1aSopenharmony_ci{ 1171cabdff1aSopenharmony_ci if (memcmp(p->buf, ".R1M\x0\x1\x1", 7) && 1172cabdff1aSopenharmony_ci memcmp(p->buf, ".REC", 4)) 1173cabdff1aSopenharmony_ci return 0; 1174cabdff1aSopenharmony_ci 1175cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 1176cabdff1aSopenharmony_ci} 1177cabdff1aSopenharmony_ci 1178cabdff1aSopenharmony_cistatic int ivr_read_header(AVFormatContext *s) 1179cabdff1aSopenharmony_ci{ 1180cabdff1aSopenharmony_ci unsigned tag, type, len, tlen, value; 1181cabdff1aSopenharmony_ci int i, j, n, count, nb_streams = 0, ret; 1182cabdff1aSopenharmony_ci uint8_t key[256], val[256]; 1183cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 1184cabdff1aSopenharmony_ci AVStream *st; 1185cabdff1aSopenharmony_ci int64_t pos, offset=0, temp; 1186cabdff1aSopenharmony_ci 1187cabdff1aSopenharmony_ci pos = avio_tell(pb); 1188cabdff1aSopenharmony_ci tag = avio_rl32(pb); 1189cabdff1aSopenharmony_ci if (tag == MKTAG('.','R','1','M')) { 1190cabdff1aSopenharmony_ci if (avio_rb16(pb) != 1) 1191cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1192cabdff1aSopenharmony_ci if (avio_r8(pb) != 1) 1193cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1194cabdff1aSopenharmony_ci len = avio_rb32(pb); 1195cabdff1aSopenharmony_ci avio_skip(pb, len); 1196cabdff1aSopenharmony_ci avio_skip(pb, 5); 1197cabdff1aSopenharmony_ci temp = avio_rb64(pb); 1198cabdff1aSopenharmony_ci while (!avio_feof(pb) && temp) { 1199cabdff1aSopenharmony_ci offset = temp; 1200cabdff1aSopenharmony_ci temp = avio_rb64(pb); 1201cabdff1aSopenharmony_ci } 1202cabdff1aSopenharmony_ci if (offset <= 0) 1203cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1204cabdff1aSopenharmony_ci avio_skip(pb, offset - avio_tell(pb)); 1205cabdff1aSopenharmony_ci if (avio_r8(pb) != 1) 1206cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1207cabdff1aSopenharmony_ci len = avio_rb32(pb); 1208cabdff1aSopenharmony_ci avio_skip(pb, len); 1209cabdff1aSopenharmony_ci if (avio_r8(pb) != 2) 1210cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1211cabdff1aSopenharmony_ci avio_skip(pb, 16); 1212cabdff1aSopenharmony_ci pos = avio_tell(pb); 1213cabdff1aSopenharmony_ci tag = avio_rl32(pb); 1214cabdff1aSopenharmony_ci } 1215cabdff1aSopenharmony_ci 1216cabdff1aSopenharmony_ci if (tag != MKTAG('.','R','E','C')) 1217cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1218cabdff1aSopenharmony_ci 1219cabdff1aSopenharmony_ci if (avio_r8(pb) != 0) 1220cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1221cabdff1aSopenharmony_ci count = avio_rb32(pb); 1222cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 1223cabdff1aSopenharmony_ci if (avio_feof(pb)) 1224cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1225cabdff1aSopenharmony_ci 1226cabdff1aSopenharmony_ci type = avio_r8(pb); 1227cabdff1aSopenharmony_ci tlen = avio_rb32(pb); 1228cabdff1aSopenharmony_ci avio_get_str(pb, tlen, key, sizeof(key)); 1229cabdff1aSopenharmony_ci len = avio_rb32(pb); 1230cabdff1aSopenharmony_ci if (type == 5) { 1231cabdff1aSopenharmony_ci avio_get_str(pb, len, val, sizeof(val)); 1232cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%s = '%s'\n", key, val); 1233cabdff1aSopenharmony_ci } else if (type == 4) { 1234cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%s = '0x", key); 1235cabdff1aSopenharmony_ci for (j = 0; j < len; j++) { 1236cabdff1aSopenharmony_ci if (avio_feof(pb)) 1237cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1238cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%X", avio_r8(pb)); 1239cabdff1aSopenharmony_ci } 1240cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "'\n"); 1241cabdff1aSopenharmony_ci } else if (len == 4 && type == 3 && !strncmp(key, "StreamCount", tlen)) { 1242cabdff1aSopenharmony_ci nb_streams = value = avio_rb32(pb); 1243cabdff1aSopenharmony_ci } else if (len == 4 && type == 3) { 1244cabdff1aSopenharmony_ci value = avio_rb32(pb); 1245cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%s = %d\n", key, value); 1246cabdff1aSopenharmony_ci } else { 1247cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "Skipping unsupported key: %s\n", key); 1248cabdff1aSopenharmony_ci avio_skip(pb, len); 1249cabdff1aSopenharmony_ci } 1250cabdff1aSopenharmony_ci } 1251cabdff1aSopenharmony_ci 1252cabdff1aSopenharmony_ci for (n = 0; n < nb_streams; n++) { 1253cabdff1aSopenharmony_ci if (!(st = avformat_new_stream(s, NULL)) || 1254cabdff1aSopenharmony_ci !(st->priv_data = ff_rm_alloc_rmstream())) 1255cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 1256cabdff1aSopenharmony_ci 1257cabdff1aSopenharmony_ci if (avio_r8(pb) != 1) 1258cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1259cabdff1aSopenharmony_ci 1260cabdff1aSopenharmony_ci count = avio_rb32(pb); 1261cabdff1aSopenharmony_ci for (i = 0; i < count; i++) { 1262cabdff1aSopenharmony_ci if (avio_feof(pb)) 1263cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1264cabdff1aSopenharmony_ci 1265cabdff1aSopenharmony_ci type = avio_r8(pb); 1266cabdff1aSopenharmony_ci tlen = avio_rb32(pb); 1267cabdff1aSopenharmony_ci avio_get_str(pb, tlen, key, sizeof(key)); 1268cabdff1aSopenharmony_ci len = avio_rb32(pb); 1269cabdff1aSopenharmony_ci if (type == 5) { 1270cabdff1aSopenharmony_ci avio_get_str(pb, len, val, sizeof(val)); 1271cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%s = '%s'\n", key, val); 1272cabdff1aSopenharmony_ci } else if (type == 4 && !strncmp(key, "OpaqueData", tlen)) { 1273cabdff1aSopenharmony_ci ret = ffio_ensure_seekback(pb, 4); 1274cabdff1aSopenharmony_ci if (ret < 0) 1275cabdff1aSopenharmony_ci return ret; 1276cabdff1aSopenharmony_ci if (avio_rb32(pb) == MKBETAG('M', 'L', 'T', 'I')) { 1277cabdff1aSopenharmony_ci ret = rm_read_multi(s, pb, st, NULL); 1278cabdff1aSopenharmony_ci } else { 1279cabdff1aSopenharmony_ci if (avio_feof(pb)) 1280cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1281cabdff1aSopenharmony_ci avio_seek(pb, -4, SEEK_CUR); 1282cabdff1aSopenharmony_ci ret = ff_rm_read_mdpr_codecdata(s, pb, st, st->priv_data, len, NULL); 1283cabdff1aSopenharmony_ci } 1284cabdff1aSopenharmony_ci 1285cabdff1aSopenharmony_ci if (ret < 0) 1286cabdff1aSopenharmony_ci return ret; 1287cabdff1aSopenharmony_ci } else if (type == 4) { 1288cabdff1aSopenharmony_ci int j; 1289cabdff1aSopenharmony_ci 1290cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%s = '0x", key); 1291cabdff1aSopenharmony_ci for (j = 0; j < len; j++) { 1292cabdff1aSopenharmony_ci if (avio_feof(pb)) 1293cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1294cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%X", avio_r8(pb)); 1295cabdff1aSopenharmony_ci } 1296cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "'\n"); 1297cabdff1aSopenharmony_ci } else if (len == 4 && type == 3 && !strncmp(key, "Duration", tlen)) { 1298cabdff1aSopenharmony_ci st->duration = avio_rb32(pb); 1299cabdff1aSopenharmony_ci } else if (len == 4 && type == 3) { 1300cabdff1aSopenharmony_ci value = avio_rb32(pb); 1301cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "%s = %d\n", key, value); 1302cabdff1aSopenharmony_ci } else { 1303cabdff1aSopenharmony_ci av_log(s, AV_LOG_DEBUG, "Skipping unsupported key: %s\n", key); 1304cabdff1aSopenharmony_ci avio_skip(pb, len); 1305cabdff1aSopenharmony_ci } 1306cabdff1aSopenharmony_ci } 1307cabdff1aSopenharmony_ci } 1308cabdff1aSopenharmony_ci 1309cabdff1aSopenharmony_ci if (avio_r8(pb) != 6) 1310cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1311cabdff1aSopenharmony_ci avio_skip(pb, 12); 1312cabdff1aSopenharmony_ci avio_seek(pb, avio_rb64(pb) + pos, SEEK_SET); 1313cabdff1aSopenharmony_ci if (avio_r8(pb) != 8) 1314cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1315cabdff1aSopenharmony_ci avio_skip(pb, 8); 1316cabdff1aSopenharmony_ci 1317cabdff1aSopenharmony_ci return 0; 1318cabdff1aSopenharmony_ci} 1319cabdff1aSopenharmony_ci 1320cabdff1aSopenharmony_cistatic int ivr_read_packet(AVFormatContext *s, AVPacket *pkt) 1321cabdff1aSopenharmony_ci{ 1322cabdff1aSopenharmony_ci RMDemuxContext *rm = s->priv_data; 1323cabdff1aSopenharmony_ci int ret = AVERROR_EOF, opcode; 1324cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 1325cabdff1aSopenharmony_ci unsigned size, index; 1326cabdff1aSopenharmony_ci int64_t pos, pts; 1327cabdff1aSopenharmony_ci 1328cabdff1aSopenharmony_ci if (avio_feof(pb) || rm->data_end) 1329cabdff1aSopenharmony_ci return AVERROR_EOF; 1330cabdff1aSopenharmony_ci 1331cabdff1aSopenharmony_ci pos = avio_tell(pb); 1332cabdff1aSopenharmony_ci 1333cabdff1aSopenharmony_ci for (;;) { 1334cabdff1aSopenharmony_ci if (rm->audio_pkt_cnt) { 1335cabdff1aSopenharmony_ci // If there are queued audio packet return them first 1336cabdff1aSopenharmony_ci AVStream *st; 1337cabdff1aSopenharmony_ci 1338cabdff1aSopenharmony_ci st = s->streams[rm->audio_stream_num]; 1339cabdff1aSopenharmony_ci ret = ff_rm_retrieve_cache(s, pb, st, st->priv_data, pkt); 1340cabdff1aSopenharmony_ci if (ret < 0) { 1341cabdff1aSopenharmony_ci return ret; 1342cabdff1aSopenharmony_ci } 1343cabdff1aSopenharmony_ci } else { 1344cabdff1aSopenharmony_ci if (rm->remaining_len) { 1345cabdff1aSopenharmony_ci avio_skip(pb, rm->remaining_len); 1346cabdff1aSopenharmony_ci rm->remaining_len = 0; 1347cabdff1aSopenharmony_ci } 1348cabdff1aSopenharmony_ci 1349cabdff1aSopenharmony_ci if (avio_feof(pb)) 1350cabdff1aSopenharmony_ci return AVERROR_EOF; 1351cabdff1aSopenharmony_ci 1352cabdff1aSopenharmony_ci opcode = avio_r8(pb); 1353cabdff1aSopenharmony_ci if (opcode == 2) { 1354cabdff1aSopenharmony_ci AVStream *st; 1355cabdff1aSopenharmony_ci int seq = 1; 1356cabdff1aSopenharmony_ci 1357cabdff1aSopenharmony_ci pts = avio_rb32(pb); 1358cabdff1aSopenharmony_ci index = avio_rb16(pb); 1359cabdff1aSopenharmony_ci if (index >= s->nb_streams) 1360cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1361cabdff1aSopenharmony_ci 1362cabdff1aSopenharmony_ci avio_skip(pb, 4); 1363cabdff1aSopenharmony_ci size = avio_rb32(pb); 1364cabdff1aSopenharmony_ci avio_skip(pb, 4); 1365cabdff1aSopenharmony_ci 1366cabdff1aSopenharmony_ci if (size < 1 || size > INT_MAX/4) { 1367cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "size %u is invalid\n", size); 1368cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 1369cabdff1aSopenharmony_ci } 1370cabdff1aSopenharmony_ci 1371cabdff1aSopenharmony_ci st = s->streams[index]; 1372cabdff1aSopenharmony_ci ret = ff_rm_parse_packet(s, pb, st, st->priv_data, size, pkt, 1373cabdff1aSopenharmony_ci &seq, 0, pts); 1374cabdff1aSopenharmony_ci if (ret < -1) { 1375cabdff1aSopenharmony_ci return ret; 1376cabdff1aSopenharmony_ci } else if (ret) { 1377cabdff1aSopenharmony_ci continue; 1378cabdff1aSopenharmony_ci } 1379cabdff1aSopenharmony_ci 1380cabdff1aSopenharmony_ci pkt->pos = pos; 1381cabdff1aSopenharmony_ci pkt->pts = pts; 1382cabdff1aSopenharmony_ci pkt->stream_index = index; 1383cabdff1aSopenharmony_ci } else if (opcode == 7) { 1384cabdff1aSopenharmony_ci pos = avio_rb64(pb); 1385cabdff1aSopenharmony_ci if (!pos) { 1386cabdff1aSopenharmony_ci rm->data_end = 1; 1387cabdff1aSopenharmony_ci return AVERROR_EOF; 1388cabdff1aSopenharmony_ci } 1389cabdff1aSopenharmony_ci } else { 1390cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "Unsupported opcode=%d at %"PRIX64"\n", opcode, avio_tell(pb) - 1); 1391cabdff1aSopenharmony_ci return AVERROR(EIO); 1392cabdff1aSopenharmony_ci } 1393cabdff1aSopenharmony_ci } 1394cabdff1aSopenharmony_ci 1395cabdff1aSopenharmony_ci break; 1396cabdff1aSopenharmony_ci } 1397cabdff1aSopenharmony_ci 1398cabdff1aSopenharmony_ci return ret; 1399cabdff1aSopenharmony_ci} 1400cabdff1aSopenharmony_ci 1401cabdff1aSopenharmony_ciconst AVInputFormat ff_ivr_demuxer = { 1402cabdff1aSopenharmony_ci .name = "ivr", 1403cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("IVR (Internet Video Recording)"), 1404cabdff1aSopenharmony_ci .priv_data_size = sizeof(RMDemuxContext), 1405cabdff1aSopenharmony_ci .flags_internal = FF_FMT_INIT_CLEANUP, 1406cabdff1aSopenharmony_ci .read_probe = ivr_probe, 1407cabdff1aSopenharmony_ci .read_header = ivr_read_header, 1408cabdff1aSopenharmony_ci .read_packet = ivr_read_packet, 1409cabdff1aSopenharmony_ci .read_close = rm_read_close, 1410cabdff1aSopenharmony_ci .extensions = "ivr", 1411cabdff1aSopenharmony_ci}; 1412