1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Vividas VIV format Demuxer 3cabdff1aSopenharmony_ci * Copyright (c) 2012 Krzysztof Klinikowski 4cabdff1aSopenharmony_ci * Copyright (c) 2010 Andrzej Szombierski 5cabdff1aSopenharmony_ci * based on vivparse Copyright (c) 2007 Måns Rullgård 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci/** 25cabdff1aSopenharmony_ci * @file 26cabdff1aSopenharmony_ci * @brief Vividas VIV (.viv) file demuxer 27cabdff1aSopenharmony_ci * @author Andrzej Szombierski [qq at kuku eu org] (2010-07) 28cabdff1aSopenharmony_ci * @sa http://wiki.multimedia.cx/index.php?title=Vividas_VIV 29cabdff1aSopenharmony_ci */ 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 32cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 33cabdff1aSopenharmony_ci#include "avio_internal.h" 34cabdff1aSopenharmony_ci#include "avformat.h" 35cabdff1aSopenharmony_ci#include "internal.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci#define MAX_AUDIO_SUBPACKETS 100 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_citypedef struct VIV_SB_block { 40cabdff1aSopenharmony_ci int size, n_packets; 41cabdff1aSopenharmony_ci int64_t byte_offset; 42cabdff1aSopenharmony_ci int64_t packet_offset; 43cabdff1aSopenharmony_ci} VIV_SB_block; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_citypedef struct VIV_SB_entry { 46cabdff1aSopenharmony_ci int size, flag; 47cabdff1aSopenharmony_ci} VIV_SB_entry; 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_citypedef struct VIV_AudioSubpacket { 50cabdff1aSopenharmony_ci int start, pcm_bytes; 51cabdff1aSopenharmony_ci} VIV_AudioSubpacket; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_citypedef struct VividasDemuxContext { 54cabdff1aSopenharmony_ci int n_sb_blocks; 55cabdff1aSopenharmony_ci VIV_SB_block *sb_blocks; 56cabdff1aSopenharmony_ci int num_audio; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_ci uint32_t sb_key; 59cabdff1aSopenharmony_ci int64_t sb_offset; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_ci int current_sb, current_sb_entry; 62cabdff1aSopenharmony_ci uint8_t *sb_buf; 63cabdff1aSopenharmony_ci AVIOContext *sb_pb; 64cabdff1aSopenharmony_ci int n_sb_entries; 65cabdff1aSopenharmony_ci VIV_SB_entry *sb_entries; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci int n_audio_subpackets; 68cabdff1aSopenharmony_ci int current_audio_subpacket; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci int64_t audio_sample; 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_ci VIV_AudioSubpacket audio_subpackets[MAX_AUDIO_SUBPACKETS]; 73cabdff1aSopenharmony_ci} VividasDemuxContext; 74cabdff1aSopenharmony_ci 75cabdff1aSopenharmony_cistatic int viv_probe(const AVProbeData *p) 76cabdff1aSopenharmony_ci{ 77cabdff1aSopenharmony_ci if (memcmp(p->buf, "vividas03", 9)) 78cabdff1aSopenharmony_ci return 0; 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 81cabdff1aSopenharmony_ci} 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_cistatic const uint8_t keybits[32] = { 84cabdff1aSopenharmony_ci 20, 52, 111, 10, 27, 71, 142, 53, 85cabdff1aSopenharmony_ci 82, 138, 1, 78, 86, 121, 183, 85, 86cabdff1aSopenharmony_ci105, 152, 39, 140, 172, 11, 64, 144, 87cabdff1aSopenharmony_ci155, 6, 71, 163, 186, 49, 126, 43, 88cabdff1aSopenharmony_ci}; 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_cistatic uint32_t decode_key(uint8_t *buf) 91cabdff1aSopenharmony_ci{ 92cabdff1aSopenharmony_ci uint32_t key = 0; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci for (int i = 0; i < 32; i++) { 95cabdff1aSopenharmony_ci unsigned p = keybits[i]; 96cabdff1aSopenharmony_ci key |= ((buf[p] >> ((i*5+3)&7)) & 1u) << i; 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci return key; 100cabdff1aSopenharmony_ci} 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_cistatic void put_v(uint8_t *p, unsigned v) 103cabdff1aSopenharmony_ci{ 104cabdff1aSopenharmony_ci if (v>>28) 105cabdff1aSopenharmony_ci *p++ = ((v>>28)&0x7f)|0x80; 106cabdff1aSopenharmony_ci if (v>>21) 107cabdff1aSopenharmony_ci *p++ = ((v>>21)&0x7f)|0x80; 108cabdff1aSopenharmony_ci if (v>>14) 109cabdff1aSopenharmony_ci *p++ = ((v>>14)&0x7f)|0x80; 110cabdff1aSopenharmony_ci if (v>>7) 111cabdff1aSopenharmony_ci *p++ = ((v>>7)&0x7f)|0x80; 112cabdff1aSopenharmony_ci} 113cabdff1aSopenharmony_ci 114cabdff1aSopenharmony_cistatic unsigned recover_key(unsigned char sample[4], unsigned expected_size) 115cabdff1aSopenharmony_ci{ 116cabdff1aSopenharmony_ci unsigned char plaintext[8] = { 'S', 'B' }; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci put_v(plaintext+2, expected_size); 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_ci return AV_RL32(sample) ^ AV_RL32(plaintext); 121cabdff1aSopenharmony_ci} 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_cistatic void xor_block(void *p1, void *p2, unsigned size, int key, unsigned *key_ptr) 124cabdff1aSopenharmony_ci{ 125cabdff1aSopenharmony_ci unsigned *d1 = p1; 126cabdff1aSopenharmony_ci unsigned *d2 = p2; 127cabdff1aSopenharmony_ci unsigned k = *key_ptr; 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci size >>= 2; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci while (size > 0) { 132cabdff1aSopenharmony_ci *d2 = *d1 ^ (HAVE_BIGENDIAN ? av_bswap32(k) : k); 133cabdff1aSopenharmony_ci k += key; 134cabdff1aSopenharmony_ci d1++; 135cabdff1aSopenharmony_ci d2++; 136cabdff1aSopenharmony_ci size--; 137cabdff1aSopenharmony_ci } 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci *key_ptr = k; 140cabdff1aSopenharmony_ci} 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_cistatic void decode_block(uint8_t *src, uint8_t *dest, unsigned size, 143cabdff1aSopenharmony_ci uint32_t key, uint32_t *key_ptr, 144cabdff1aSopenharmony_ci int align) 145cabdff1aSopenharmony_ci{ 146cabdff1aSopenharmony_ci unsigned s = size; 147cabdff1aSopenharmony_ci char tmp[4]; 148cabdff1aSopenharmony_ci int a2; 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci if (!size) 151cabdff1aSopenharmony_ci return; 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci align &= 3; 154cabdff1aSopenharmony_ci a2 = (4 - align) & 3; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci if (align) { 157cabdff1aSopenharmony_ci uint32_t tmpkey = *key_ptr - key; 158cabdff1aSopenharmony_ci if (a2 > s) { 159cabdff1aSopenharmony_ci a2 = s; 160cabdff1aSopenharmony_ci avpriv_request_sample(NULL, "tiny aligned block"); 161cabdff1aSopenharmony_ci } 162cabdff1aSopenharmony_ci memcpy(tmp + align, src, a2); 163cabdff1aSopenharmony_ci xor_block(tmp, tmp, 4, key, &tmpkey); 164cabdff1aSopenharmony_ci memcpy(dest, tmp + align, a2); 165cabdff1aSopenharmony_ci s -= a2; 166cabdff1aSopenharmony_ci } 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci if (s >= 4) { 169cabdff1aSopenharmony_ci xor_block(src + a2, dest + a2, s & ~3, 170cabdff1aSopenharmony_ci key, key_ptr); 171cabdff1aSopenharmony_ci s &= 3; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci if (s) { 175cabdff1aSopenharmony_ci size -= s; 176cabdff1aSopenharmony_ci memcpy(tmp, src + size, s); 177cabdff1aSopenharmony_ci xor_block(&tmp, &tmp, 4, key, key_ptr); 178cabdff1aSopenharmony_ci memcpy(dest + size, tmp, s); 179cabdff1aSopenharmony_ci } 180cabdff1aSopenharmony_ci} 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_cistatic uint32_t get_v(uint8_t *p, int len) 183cabdff1aSopenharmony_ci{ 184cabdff1aSopenharmony_ci uint32_t v = 0; 185cabdff1aSopenharmony_ci const uint8_t *end = p + len; 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci do { 188cabdff1aSopenharmony_ci if (p >= end || v >= UINT_MAX / 128 - *p) 189cabdff1aSopenharmony_ci return v; 190cabdff1aSopenharmony_ci v <<= 7; 191cabdff1aSopenharmony_ci v += *p & 0x7f; 192cabdff1aSopenharmony_ci } while (*p++ & 0x80); 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci return v; 195cabdff1aSopenharmony_ci} 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_cistatic uint8_t *read_vblock(AVIOContext *src, uint32_t *size, 198cabdff1aSopenharmony_ci uint32_t key, uint32_t *k2, int align) 199cabdff1aSopenharmony_ci{ 200cabdff1aSopenharmony_ci uint8_t tmp[4]; 201cabdff1aSopenharmony_ci uint8_t *buf; 202cabdff1aSopenharmony_ci unsigned n; 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci if (avio_read(src, tmp, 4) != 4) 205cabdff1aSopenharmony_ci return NULL; 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci decode_block(tmp, tmp, 4, key, k2, align); 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci n = get_v(tmp, 4); 210cabdff1aSopenharmony_ci if (n < 4) 211cabdff1aSopenharmony_ci return NULL; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci buf = av_malloc(n); 214cabdff1aSopenharmony_ci if (!buf) 215cabdff1aSopenharmony_ci return NULL; 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci *size = n; 218cabdff1aSopenharmony_ci n -= 4; 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci memcpy(buf, tmp, 4); 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci if (avio_read(src, buf + 4, n) == n) { 223cabdff1aSopenharmony_ci decode_block(buf + 4, buf + 4, n, key, k2, align); 224cabdff1aSopenharmony_ci } else { 225cabdff1aSopenharmony_ci av_free(buf); 226cabdff1aSopenharmony_ci buf = NULL; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci return buf; 230cabdff1aSopenharmony_ci} 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_cistatic uint8_t *read_sb_block(AVIOContext *src, unsigned *size, 233cabdff1aSopenharmony_ci uint32_t *key, unsigned expected_size) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci uint8_t *buf; 236cabdff1aSopenharmony_ci uint8_t ibuf[8], sbuf[8]; 237cabdff1aSopenharmony_ci uint32_t k2; 238cabdff1aSopenharmony_ci unsigned n; 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci if (avio_read(src, ibuf, 8) < 8) 241cabdff1aSopenharmony_ci return NULL; 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci k2 = *key; 244cabdff1aSopenharmony_ci decode_block(ibuf, sbuf, 8, *key, &k2, 0); 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci n = get_v(sbuf+2, 6); 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci if (sbuf[0] != 'S' || sbuf[1] != 'B' || (expected_size>0 && n != expected_size)) { 249cabdff1aSopenharmony_ci uint32_t tmpkey = recover_key(ibuf, expected_size); 250cabdff1aSopenharmony_ci k2 = tmpkey; 251cabdff1aSopenharmony_ci decode_block(ibuf, sbuf, 8, tmpkey, &k2, 0); 252cabdff1aSopenharmony_ci n = get_v(sbuf+2, 6); 253cabdff1aSopenharmony_ci if (sbuf[0] != 'S' || sbuf[1] != 'B' || expected_size != n) 254cabdff1aSopenharmony_ci return NULL; 255cabdff1aSopenharmony_ci *key = tmpkey; 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci if (n < 8) 259cabdff1aSopenharmony_ci return NULL; 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci buf = av_malloc(n); 262cabdff1aSopenharmony_ci if (!buf) 263cabdff1aSopenharmony_ci return NULL; 264cabdff1aSopenharmony_ci 265cabdff1aSopenharmony_ci memcpy(buf, sbuf, 8); 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci *size = n; 268cabdff1aSopenharmony_ci n -= 8; 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci if (avio_read(src, buf+8, n) != n) { 271cabdff1aSopenharmony_ci av_free(buf); 272cabdff1aSopenharmony_ci return NULL; 273cabdff1aSopenharmony_ci } 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci decode_block(buf + 8, buf + 8, n, *key, &k2, 0); 276cabdff1aSopenharmony_ci 277cabdff1aSopenharmony_ci return buf; 278cabdff1aSopenharmony_ci} 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_cistatic int track_header(VividasDemuxContext *viv, AVFormatContext *s, uint8_t *buf, int size) 281cabdff1aSopenharmony_ci{ 282cabdff1aSopenharmony_ci int i, j, ret; 283cabdff1aSopenharmony_ci int64_t off; 284cabdff1aSopenharmony_ci int val_1; 285cabdff1aSopenharmony_ci int num_video; 286cabdff1aSopenharmony_ci FFIOContext pb0; 287cabdff1aSopenharmony_ci AVIOContext *const pb = &pb0.pub; 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci ffio_init_context(&pb0, buf, size, 0, NULL, NULL, NULL, NULL); 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci ffio_read_varlen(pb); // track_header_len 292cabdff1aSopenharmony_ci avio_r8(pb); // '1' 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci val_1 = ffio_read_varlen(pb); 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci for (i=0;i<val_1;i++) { 297cabdff1aSopenharmony_ci int c = avio_r8(pb); 298cabdff1aSopenharmony_ci if (avio_feof(pb)) 299cabdff1aSopenharmony_ci return AVERROR_EOF; 300cabdff1aSopenharmony_ci for (j=0;j<c;j++) { 301cabdff1aSopenharmony_ci if (avio_feof(pb)) 302cabdff1aSopenharmony_ci return AVERROR_EOF; 303cabdff1aSopenharmony_ci avio_r8(pb); // val_3 304cabdff1aSopenharmony_ci avio_r8(pb); // val_4 305cabdff1aSopenharmony_ci } 306cabdff1aSopenharmony_ci } 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_ci avio_r8(pb); // num_streams 309cabdff1aSopenharmony_ci 310cabdff1aSopenharmony_ci off = avio_tell(pb); 311cabdff1aSopenharmony_ci off += ffio_read_varlen(pb); // val_5 312cabdff1aSopenharmony_ci 313cabdff1aSopenharmony_ci avio_r8(pb); // '2' 314cabdff1aSopenharmony_ci num_video = avio_r8(pb); 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_ci avio_seek(pb, off, SEEK_SET); 317cabdff1aSopenharmony_ci if (num_video != 1) { 318cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "number of video tracks %d is not 1\n", num_video); 319cabdff1aSopenharmony_ci return AVERROR_PATCHWELCOME; 320cabdff1aSopenharmony_ci } 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_ci for (i = 0; i < num_video; i++) { 323cabdff1aSopenharmony_ci AVStream *st = avformat_new_stream(s, NULL); 324cabdff1aSopenharmony_ci int num, den; 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_ci if (!st) 327cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_ci st->id = i; 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; 332cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_VP6; 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci off = avio_tell(pb); 335cabdff1aSopenharmony_ci off += ffio_read_varlen(pb); 336cabdff1aSopenharmony_ci avio_r8(pb); // '3' 337cabdff1aSopenharmony_ci avio_r8(pb); // val_7 338cabdff1aSopenharmony_ci num = avio_rl32(pb); // frame_time 339cabdff1aSopenharmony_ci den = avio_rl32(pb); // time_base 340cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 64, num, den); 341cabdff1aSopenharmony_ci st->nb_frames = avio_rl32(pb); // n frames 342cabdff1aSopenharmony_ci st->codecpar->width = avio_rl16(pb); // width 343cabdff1aSopenharmony_ci st->codecpar->height = avio_rl16(pb); // height 344cabdff1aSopenharmony_ci avio_r8(pb); // val_8 345cabdff1aSopenharmony_ci avio_rl32(pb); // val_9 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci avio_seek(pb, off, SEEK_SET); 348cabdff1aSopenharmony_ci } 349cabdff1aSopenharmony_ci 350cabdff1aSopenharmony_ci off = avio_tell(pb); 351cabdff1aSopenharmony_ci off += ffio_read_varlen(pb); // val_10 352cabdff1aSopenharmony_ci avio_r8(pb); // '4' 353cabdff1aSopenharmony_ci viv->num_audio = avio_r8(pb); 354cabdff1aSopenharmony_ci avio_seek(pb, off, SEEK_SET); 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ci if (viv->num_audio != 1) 357cabdff1aSopenharmony_ci av_log(s, AV_LOG_WARNING, "number of audio tracks %d is not 1\n", viv->num_audio); 358cabdff1aSopenharmony_ci 359cabdff1aSopenharmony_ci for(i=0;i<viv->num_audio;i++) { 360cabdff1aSopenharmony_ci int q; 361cabdff1aSopenharmony_ci AVStream *st = avformat_new_stream(s, NULL); 362cabdff1aSopenharmony_ci if (!st) 363cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 364cabdff1aSopenharmony_ci 365cabdff1aSopenharmony_ci st->id = num_video + i; 366cabdff1aSopenharmony_ci 367cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 368cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_VORBIS; 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci off = avio_tell(pb); 371cabdff1aSopenharmony_ci off += ffio_read_varlen(pb); // length 372cabdff1aSopenharmony_ci avio_r8(pb); // '5' 373cabdff1aSopenharmony_ci avio_r8(pb); //codec_id 374cabdff1aSopenharmony_ci avio_rl16(pb); //codec_subid 375cabdff1aSopenharmony_ci st->codecpar->ch_layout.nb_channels = avio_rl16(pb); // channels 376cabdff1aSopenharmony_ci st->codecpar->sample_rate = avio_rl32(pb); // sample_rate 377cabdff1aSopenharmony_ci if (st->codecpar->sample_rate <= 0 || st->codecpar->ch_layout.nb_channels <= 0) 378cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 379cabdff1aSopenharmony_ci avio_seek(pb, 10, SEEK_CUR); // data_1 380cabdff1aSopenharmony_ci q = avio_r8(pb); 381cabdff1aSopenharmony_ci avio_seek(pb, q, SEEK_CUR); // data_2 382cabdff1aSopenharmony_ci avio_r8(pb); // zeropad 383cabdff1aSopenharmony_ci 384cabdff1aSopenharmony_ci if (avio_tell(pb) < off) { 385cabdff1aSopenharmony_ci int num_data; 386cabdff1aSopenharmony_ci int xd_size = 1; 387cabdff1aSopenharmony_ci int data_len[256]; 388cabdff1aSopenharmony_ci int offset = 1; 389cabdff1aSopenharmony_ci uint8_t *p; 390cabdff1aSopenharmony_ci ffio_read_varlen(pb); // val_13 391cabdff1aSopenharmony_ci avio_r8(pb); // '19' 392cabdff1aSopenharmony_ci ffio_read_varlen(pb); // len_3 393cabdff1aSopenharmony_ci num_data = avio_r8(pb); 394cabdff1aSopenharmony_ci for (j = 0; j < num_data; j++) { 395cabdff1aSopenharmony_ci int64_t len = ffio_read_varlen(pb); 396cabdff1aSopenharmony_ci if (len < 0 || len > INT_MAX/2 - xd_size) { 397cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 398cabdff1aSopenharmony_ci } 399cabdff1aSopenharmony_ci data_len[j] = len; 400cabdff1aSopenharmony_ci xd_size += len + 1 + len/255; 401cabdff1aSopenharmony_ci } 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_ci ret = ff_alloc_extradata(st->codecpar, xd_size); 404cabdff1aSopenharmony_ci if (ret < 0) 405cabdff1aSopenharmony_ci return ret; 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci p = st->codecpar->extradata; 408cabdff1aSopenharmony_ci p[0] = 2; 409cabdff1aSopenharmony_ci 410cabdff1aSopenharmony_ci for (j = 0; j < num_data - 1; j++) { 411cabdff1aSopenharmony_ci unsigned delta = av_xiphlacing(&p[offset], data_len[j]); 412cabdff1aSopenharmony_ci av_assert0(delta <= xd_size - offset); 413cabdff1aSopenharmony_ci offset += delta; 414cabdff1aSopenharmony_ci } 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci for (j = 0; j < num_data; j++) { 417cabdff1aSopenharmony_ci int ret = avio_read(pb, &p[offset], data_len[j]); 418cabdff1aSopenharmony_ci if (ret < data_len[j]) { 419cabdff1aSopenharmony_ci st->codecpar->extradata_size = 0; 420cabdff1aSopenharmony_ci av_freep(&st->codecpar->extradata); 421cabdff1aSopenharmony_ci break; 422cabdff1aSopenharmony_ci } 423cabdff1aSopenharmony_ci av_assert0(data_len[j] <= xd_size - offset); 424cabdff1aSopenharmony_ci offset += data_len[j]; 425cabdff1aSopenharmony_ci } 426cabdff1aSopenharmony_ci 427cabdff1aSopenharmony_ci if (offset < st->codecpar->extradata_size) 428cabdff1aSopenharmony_ci st->codecpar->extradata_size = offset; 429cabdff1aSopenharmony_ci } 430cabdff1aSopenharmony_ci } 431cabdff1aSopenharmony_ci 432cabdff1aSopenharmony_ci return 0; 433cabdff1aSopenharmony_ci} 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_cistatic int track_index(VividasDemuxContext *viv, AVFormatContext *s, uint8_t *buf, unsigned size) 436cabdff1aSopenharmony_ci{ 437cabdff1aSopenharmony_ci int64_t off; 438cabdff1aSopenharmony_ci int64_t poff; 439cabdff1aSopenharmony_ci int maxnp=0; 440cabdff1aSopenharmony_ci FFIOContext pb0; 441cabdff1aSopenharmony_ci AVIOContext *const pb = &pb0.pub; 442cabdff1aSopenharmony_ci int i; 443cabdff1aSopenharmony_ci int64_t filesize = avio_size(s->pb); 444cabdff1aSopenharmony_ci uint64_t n_sb_blocks_tmp; 445cabdff1aSopenharmony_ci 446cabdff1aSopenharmony_ci ffio_init_context(&pb0, buf, size, 0, NULL, NULL, NULL, NULL); 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci ffio_read_varlen(pb); // track_index_len 449cabdff1aSopenharmony_ci avio_r8(pb); // 'c' 450cabdff1aSopenharmony_ci n_sb_blocks_tmp = ffio_read_varlen(pb); 451cabdff1aSopenharmony_ci if (n_sb_blocks_tmp > size / 2) 452cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 453cabdff1aSopenharmony_ci viv->sb_blocks = av_calloc(n_sb_blocks_tmp, sizeof(*viv->sb_blocks)); 454cabdff1aSopenharmony_ci if (!viv->sb_blocks) { 455cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 456cabdff1aSopenharmony_ci } 457cabdff1aSopenharmony_ci viv->n_sb_blocks = n_sb_blocks_tmp; 458cabdff1aSopenharmony_ci 459cabdff1aSopenharmony_ci off = 0; 460cabdff1aSopenharmony_ci poff = 0; 461cabdff1aSopenharmony_ci 462cabdff1aSopenharmony_ci for (i = 0; i < viv->n_sb_blocks; i++) { 463cabdff1aSopenharmony_ci uint64_t size_tmp = ffio_read_varlen(pb); 464cabdff1aSopenharmony_ci uint64_t n_packets_tmp = ffio_read_varlen(pb); 465cabdff1aSopenharmony_ci 466cabdff1aSopenharmony_ci if (size_tmp > INT_MAX || n_packets_tmp > INT_MAX) 467cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_ci viv->sb_blocks[i].byte_offset = off; 470cabdff1aSopenharmony_ci viv->sb_blocks[i].packet_offset = poff; 471cabdff1aSopenharmony_ci 472cabdff1aSopenharmony_ci viv->sb_blocks[i].size = size_tmp; 473cabdff1aSopenharmony_ci viv->sb_blocks[i].n_packets = n_packets_tmp; 474cabdff1aSopenharmony_ci 475cabdff1aSopenharmony_ci off += viv->sb_blocks[i].size; 476cabdff1aSopenharmony_ci poff += viv->sb_blocks[i].n_packets; 477cabdff1aSopenharmony_ci 478cabdff1aSopenharmony_ci if (maxnp < viv->sb_blocks[i].n_packets) 479cabdff1aSopenharmony_ci maxnp = viv->sb_blocks[i].n_packets; 480cabdff1aSopenharmony_ci } 481cabdff1aSopenharmony_ci 482cabdff1aSopenharmony_ci if (filesize > 0 && poff > filesize) 483cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 484cabdff1aSopenharmony_ci 485cabdff1aSopenharmony_ci viv->sb_entries = av_calloc(maxnp, sizeof(VIV_SB_entry)); 486cabdff1aSopenharmony_ci if (!viv->sb_entries) 487cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 488cabdff1aSopenharmony_ci 489cabdff1aSopenharmony_ci return 0; 490cabdff1aSopenharmony_ci} 491cabdff1aSopenharmony_ci 492cabdff1aSopenharmony_cistatic void load_sb_block(AVFormatContext *s, VividasDemuxContext *viv, unsigned expected_size) 493cabdff1aSopenharmony_ci{ 494cabdff1aSopenharmony_ci uint32_t size = 0; 495cabdff1aSopenharmony_ci int i; 496cabdff1aSopenharmony_ci AVIOContext *pb = 0; 497cabdff1aSopenharmony_ci 498cabdff1aSopenharmony_ci if (viv->sb_pb) { 499cabdff1aSopenharmony_ci av_free(viv->sb_pb); 500cabdff1aSopenharmony_ci viv->sb_pb = NULL; 501cabdff1aSopenharmony_ci } 502cabdff1aSopenharmony_ci 503cabdff1aSopenharmony_ci if (viv->sb_buf) 504cabdff1aSopenharmony_ci av_free(viv->sb_buf); 505cabdff1aSopenharmony_ci 506cabdff1aSopenharmony_ci viv->sb_buf = read_sb_block(s->pb, &size, &viv->sb_key, expected_size); 507cabdff1aSopenharmony_ci if (!viv->sb_buf) { 508cabdff1aSopenharmony_ci return; 509cabdff1aSopenharmony_ci } 510cabdff1aSopenharmony_ci 511cabdff1aSopenharmony_ci pb = avio_alloc_context(viv->sb_buf, size, 0, NULL, NULL, NULL, NULL); 512cabdff1aSopenharmony_ci if (!pb) 513cabdff1aSopenharmony_ci return; 514cabdff1aSopenharmony_ci 515cabdff1aSopenharmony_ci viv->sb_pb = pb; 516cabdff1aSopenharmony_ci 517cabdff1aSopenharmony_ci avio_r8(pb); // 'S' 518cabdff1aSopenharmony_ci avio_r8(pb); // 'B' 519cabdff1aSopenharmony_ci ffio_read_varlen(pb); // size 520cabdff1aSopenharmony_ci avio_r8(pb); // junk 521cabdff1aSopenharmony_ci ffio_read_varlen(pb); // first packet 522cabdff1aSopenharmony_ci 523cabdff1aSopenharmony_ci viv->n_sb_entries = viv->sb_blocks[viv->current_sb].n_packets; 524cabdff1aSopenharmony_ci 525cabdff1aSopenharmony_ci for (i = 0; i < viv->n_sb_entries; i++) { 526cabdff1aSopenharmony_ci viv->sb_entries[i].size = ffio_read_varlen(pb); 527cabdff1aSopenharmony_ci viv->sb_entries[i].flag = avio_r8(pb); 528cabdff1aSopenharmony_ci } 529cabdff1aSopenharmony_ci 530cabdff1aSopenharmony_ci ffio_read_varlen(pb); 531cabdff1aSopenharmony_ci avio_r8(pb); 532cabdff1aSopenharmony_ci 533cabdff1aSopenharmony_ci viv->current_sb_entry = 0; 534cabdff1aSopenharmony_ci} 535cabdff1aSopenharmony_ci 536cabdff1aSopenharmony_cistatic int viv_read_header(AVFormatContext *s) 537cabdff1aSopenharmony_ci{ 538cabdff1aSopenharmony_ci VividasDemuxContext *viv = s->priv_data; 539cabdff1aSopenharmony_ci AVIOContext *pb = s->pb; 540cabdff1aSopenharmony_ci int64_t header_end; 541cabdff1aSopenharmony_ci int num_tracks; 542cabdff1aSopenharmony_ci uint32_t key, k2; 543cabdff1aSopenharmony_ci uint32_t v; 544cabdff1aSopenharmony_ci uint8_t keybuffer[187]; 545cabdff1aSopenharmony_ci uint32_t b22_size = 0; 546cabdff1aSopenharmony_ci uint32_t b22_key = 0; 547cabdff1aSopenharmony_ci uint8_t *buf = 0; 548cabdff1aSopenharmony_ci int ret; 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci avio_skip(pb, 9); 551cabdff1aSopenharmony_ci 552cabdff1aSopenharmony_ci header_end = avio_tell(pb); 553cabdff1aSopenharmony_ci 554cabdff1aSopenharmony_ci header_end += ffio_read_varlen(pb); 555cabdff1aSopenharmony_ci 556cabdff1aSopenharmony_ci num_tracks = avio_r8(pb); 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_ci if (num_tracks != 1) { 559cabdff1aSopenharmony_ci av_log(s, AV_LOG_ERROR, "number of tracks %d is not 1\n", num_tracks); 560cabdff1aSopenharmony_ci return AVERROR(EINVAL); 561cabdff1aSopenharmony_ci } 562cabdff1aSopenharmony_ci 563cabdff1aSopenharmony_ci v = avio_r8(pb); 564cabdff1aSopenharmony_ci avio_seek(pb, v, SEEK_CUR); 565cabdff1aSopenharmony_ci 566cabdff1aSopenharmony_ci avio_read(pb, keybuffer, 187); 567cabdff1aSopenharmony_ci key = decode_key(keybuffer); 568cabdff1aSopenharmony_ci viv->sb_key = key; 569cabdff1aSopenharmony_ci 570cabdff1aSopenharmony_ci avio_rl32(pb); 571cabdff1aSopenharmony_ci 572cabdff1aSopenharmony_ci for (;;) { 573cabdff1aSopenharmony_ci int64_t here = avio_tell(pb); 574cabdff1aSopenharmony_ci int block_len, block_type; 575cabdff1aSopenharmony_ci 576cabdff1aSopenharmony_ci if (here >= header_end) 577cabdff1aSopenharmony_ci break; 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci block_len = ffio_read_varlen(pb); 580cabdff1aSopenharmony_ci if (avio_feof(pb) || block_len <= 0) 581cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_ci block_type = avio_r8(pb); 584cabdff1aSopenharmony_ci 585cabdff1aSopenharmony_ci if (block_type == 22) { 586cabdff1aSopenharmony_ci avio_read(pb, keybuffer, 187); 587cabdff1aSopenharmony_ci b22_key = decode_key(keybuffer); 588cabdff1aSopenharmony_ci b22_size = avio_rl32(pb); 589cabdff1aSopenharmony_ci } 590cabdff1aSopenharmony_ci 591cabdff1aSopenharmony_ci avio_seek(pb, here + block_len, SEEK_SET); 592cabdff1aSopenharmony_ci } 593cabdff1aSopenharmony_ci 594cabdff1aSopenharmony_ci if (b22_size) { 595cabdff1aSopenharmony_ci k2 = b22_key; 596cabdff1aSopenharmony_ci buf = read_vblock(pb, &v, b22_key, &k2, 0); 597cabdff1aSopenharmony_ci if (!buf) 598cabdff1aSopenharmony_ci return AVERROR(EIO); 599cabdff1aSopenharmony_ci 600cabdff1aSopenharmony_ci av_free(buf); 601cabdff1aSopenharmony_ci } 602cabdff1aSopenharmony_ci 603cabdff1aSopenharmony_ci k2 = key; 604cabdff1aSopenharmony_ci buf = read_vblock(pb, &v, key, &k2, 0); 605cabdff1aSopenharmony_ci if (!buf) 606cabdff1aSopenharmony_ci return AVERROR(EIO); 607cabdff1aSopenharmony_ci ret = track_header(viv, s, buf, v); 608cabdff1aSopenharmony_ci av_free(buf); 609cabdff1aSopenharmony_ci if (ret < 0) 610cabdff1aSopenharmony_ci return ret; 611cabdff1aSopenharmony_ci 612cabdff1aSopenharmony_ci buf = read_vblock(pb, &v, key, &k2, v); 613cabdff1aSopenharmony_ci if (!buf) 614cabdff1aSopenharmony_ci return AVERROR(EIO); 615cabdff1aSopenharmony_ci ret = track_index(viv, s, buf, v); 616cabdff1aSopenharmony_ci av_free(buf); 617cabdff1aSopenharmony_ci if (ret < 0) 618cabdff1aSopenharmony_ci return ret; 619cabdff1aSopenharmony_ci 620cabdff1aSopenharmony_ci viv->sb_offset = avio_tell(pb); 621cabdff1aSopenharmony_ci if (viv->n_sb_blocks > 0) { 622cabdff1aSopenharmony_ci viv->current_sb = 0; 623cabdff1aSopenharmony_ci load_sb_block(s, viv, viv->sb_blocks[0].size); 624cabdff1aSopenharmony_ci } else { 625cabdff1aSopenharmony_ci viv->current_sb = -1; 626cabdff1aSopenharmony_ci } 627cabdff1aSopenharmony_ci 628cabdff1aSopenharmony_ci return 0; 629cabdff1aSopenharmony_ci} 630cabdff1aSopenharmony_ci 631cabdff1aSopenharmony_cistatic int viv_read_packet(AVFormatContext *s, 632cabdff1aSopenharmony_ci AVPacket *pkt) 633cabdff1aSopenharmony_ci{ 634cabdff1aSopenharmony_ci VividasDemuxContext *viv = s->priv_data; 635cabdff1aSopenharmony_ci AVIOContext *pb; 636cabdff1aSopenharmony_ci int64_t off; 637cabdff1aSopenharmony_ci int ret; 638cabdff1aSopenharmony_ci 639cabdff1aSopenharmony_ci if (!viv->sb_pb) 640cabdff1aSopenharmony_ci return AVERROR(EIO); 641cabdff1aSopenharmony_ci if (avio_feof(viv->sb_pb)) 642cabdff1aSopenharmony_ci return AVERROR_EOF; 643cabdff1aSopenharmony_ci 644cabdff1aSopenharmony_ci if (viv->current_audio_subpacket < viv->n_audio_subpackets) { 645cabdff1aSopenharmony_ci AVStream *astream; 646cabdff1aSopenharmony_ci int size = viv->audio_subpackets[viv->current_audio_subpacket+1].start - viv->audio_subpackets[viv->current_audio_subpacket].start; 647cabdff1aSopenharmony_ci 648cabdff1aSopenharmony_ci pb = viv->sb_pb; 649cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, size); 650cabdff1aSopenharmony_ci if (ret < 0) 651cabdff1aSopenharmony_ci return ret; 652cabdff1aSopenharmony_ci pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; 653cabdff1aSopenharmony_ci 654cabdff1aSopenharmony_ci pkt->stream_index = 1; 655cabdff1aSopenharmony_ci astream = s->streams[pkt->stream_index]; 656cabdff1aSopenharmony_ci 657cabdff1aSopenharmony_ci pkt->pts = av_rescale_q(viv->audio_sample, av_make_q(1, astream->codecpar->sample_rate), astream->time_base); 658cabdff1aSopenharmony_ci viv->audio_sample += viv->audio_subpackets[viv->current_audio_subpacket].pcm_bytes / 2 / 659cabdff1aSopenharmony_ci astream->codecpar->ch_layout.nb_channels; 660cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 661cabdff1aSopenharmony_ci viv->current_audio_subpacket++; 662cabdff1aSopenharmony_ci return 0; 663cabdff1aSopenharmony_ci } 664cabdff1aSopenharmony_ci 665cabdff1aSopenharmony_ci if (viv->current_sb_entry >= viv->n_sb_entries) { 666cabdff1aSopenharmony_ci if (viv->current_sb+1 >= viv->n_sb_blocks) 667cabdff1aSopenharmony_ci return AVERROR(EIO); 668cabdff1aSopenharmony_ci viv->current_sb++; 669cabdff1aSopenharmony_ci 670cabdff1aSopenharmony_ci load_sb_block(s, viv, 0); 671cabdff1aSopenharmony_ci viv->current_sb_entry = 0; 672cabdff1aSopenharmony_ci } 673cabdff1aSopenharmony_ci 674cabdff1aSopenharmony_ci pb = viv->sb_pb; 675cabdff1aSopenharmony_ci if (!pb) 676cabdff1aSopenharmony_ci return AVERROR(EIO); 677cabdff1aSopenharmony_ci off = avio_tell(pb); 678cabdff1aSopenharmony_ci 679cabdff1aSopenharmony_ci if (viv->current_sb_entry >= viv->n_sb_entries) 680cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 681cabdff1aSopenharmony_ci 682cabdff1aSopenharmony_ci off += viv->sb_entries[viv->current_sb_entry].size; 683cabdff1aSopenharmony_ci 684cabdff1aSopenharmony_ci if (viv->sb_entries[viv->current_sb_entry].flag == 0) { 685cabdff1aSopenharmony_ci uint64_t v_size = ffio_read_varlen(pb); 686cabdff1aSopenharmony_ci int last = 0, last_start; 687cabdff1aSopenharmony_ci 688cabdff1aSopenharmony_ci if (!viv->num_audio) 689cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 690cabdff1aSopenharmony_ci 691cabdff1aSopenharmony_ci ffio_read_varlen(pb); 692cabdff1aSopenharmony_ci if (v_size > INT_MAX || !v_size) 693cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 694cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, v_size); 695cabdff1aSopenharmony_ci if (ret < 0) 696cabdff1aSopenharmony_ci return ret; 697cabdff1aSopenharmony_ci pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; 698cabdff1aSopenharmony_ci 699cabdff1aSopenharmony_ci pkt->pts = viv->sb_blocks[viv->current_sb].packet_offset + viv->current_sb_entry; 700cabdff1aSopenharmony_ci pkt->flags |= (pkt->data[0]&0x80)?0:AV_PKT_FLAG_KEY; 701cabdff1aSopenharmony_ci pkt->stream_index = 0; 702cabdff1aSopenharmony_ci 703cabdff1aSopenharmony_ci for (int i = 0; i < MAX_AUDIO_SUBPACKETS - 1; i++) { 704cabdff1aSopenharmony_ci int start, pcm_bytes; 705cabdff1aSopenharmony_ci start = ffio_read_varlen(pb); 706cabdff1aSopenharmony_ci pcm_bytes = ffio_read_varlen(pb); 707cabdff1aSopenharmony_ci 708cabdff1aSopenharmony_ci if (i > 0 && start == 0) 709cabdff1aSopenharmony_ci break; 710cabdff1aSopenharmony_ci if (start < last) 711cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 712cabdff1aSopenharmony_ci 713cabdff1aSopenharmony_ci viv->n_audio_subpackets = i + 1; 714cabdff1aSopenharmony_ci last = 715cabdff1aSopenharmony_ci viv->audio_subpackets[i].start = start; 716cabdff1aSopenharmony_ci viv->audio_subpackets[i].pcm_bytes = pcm_bytes; 717cabdff1aSopenharmony_ci } 718cabdff1aSopenharmony_ci last_start = 719cabdff1aSopenharmony_ci viv->audio_subpackets[viv->n_audio_subpackets].start = (int)(off - avio_tell(pb)); 720cabdff1aSopenharmony_ci if (last_start < last) 721cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 722cabdff1aSopenharmony_ci viv->current_audio_subpacket = 0; 723cabdff1aSopenharmony_ci 724cabdff1aSopenharmony_ci } else { 725cabdff1aSopenharmony_ci uint64_t v_size = ffio_read_varlen(pb); 726cabdff1aSopenharmony_ci 727cabdff1aSopenharmony_ci if (v_size > INT_MAX || !v_size) 728cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 729cabdff1aSopenharmony_ci ret = av_get_packet(pb, pkt, v_size); 730cabdff1aSopenharmony_ci if (ret < 0) 731cabdff1aSopenharmony_ci return ret; 732cabdff1aSopenharmony_ci pkt->pos += viv->sb_offset + viv->sb_blocks[viv->current_sb].byte_offset; 733cabdff1aSopenharmony_ci pkt->pts = viv->sb_blocks[viv->current_sb].packet_offset + viv->current_sb_entry; 734cabdff1aSopenharmony_ci pkt->flags |= (pkt->data[0] & 0x80) ? 0 : AV_PKT_FLAG_KEY; 735cabdff1aSopenharmony_ci pkt->stream_index = 0; 736cabdff1aSopenharmony_ci } 737cabdff1aSopenharmony_ci 738cabdff1aSopenharmony_ci viv->current_sb_entry++; 739cabdff1aSopenharmony_ci 740cabdff1aSopenharmony_ci return 0; 741cabdff1aSopenharmony_ci} 742cabdff1aSopenharmony_ci 743cabdff1aSopenharmony_cistatic int viv_read_close(AVFormatContext *s) 744cabdff1aSopenharmony_ci{ 745cabdff1aSopenharmony_ci VividasDemuxContext *viv = s->priv_data; 746cabdff1aSopenharmony_ci 747cabdff1aSopenharmony_ci av_freep(&viv->sb_pb); 748cabdff1aSopenharmony_ci av_freep(&viv->sb_buf); 749cabdff1aSopenharmony_ci av_freep(&viv->sb_blocks); 750cabdff1aSopenharmony_ci av_freep(&viv->sb_entries); 751cabdff1aSopenharmony_ci 752cabdff1aSopenharmony_ci return 0; 753cabdff1aSopenharmony_ci} 754cabdff1aSopenharmony_ci 755cabdff1aSopenharmony_cistatic int viv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) 756cabdff1aSopenharmony_ci{ 757cabdff1aSopenharmony_ci VividasDemuxContext *viv = s->priv_data; 758cabdff1aSopenharmony_ci int64_t frame; 759cabdff1aSopenharmony_ci 760cabdff1aSopenharmony_ci if (stream_index == 0) 761cabdff1aSopenharmony_ci frame = timestamp; 762cabdff1aSopenharmony_ci else 763cabdff1aSopenharmony_ci frame = av_rescale_q(timestamp, s->streams[0]->time_base, s->streams[stream_index]->time_base); 764cabdff1aSopenharmony_ci 765cabdff1aSopenharmony_ci for (int i = 0; i < viv->n_sb_blocks; i++) { 766cabdff1aSopenharmony_ci if (frame >= viv->sb_blocks[i].packet_offset && frame < viv->sb_blocks[i].packet_offset + viv->sb_blocks[i].n_packets) { 767cabdff1aSopenharmony_ci viv->current_sb = i; 768cabdff1aSopenharmony_ci // seek to ith sb block 769cabdff1aSopenharmony_ci avio_seek(s->pb, viv->sb_offset + viv->sb_blocks[i].byte_offset, SEEK_SET); 770cabdff1aSopenharmony_ci // load the block 771cabdff1aSopenharmony_ci load_sb_block(s, viv, 0); 772cabdff1aSopenharmony_ci if (viv->num_audio) { 773cabdff1aSopenharmony_ci const AVCodecParameters *par = s->streams[1]->codecpar; 774cabdff1aSopenharmony_ci // flush audio packet queue 775cabdff1aSopenharmony_ci viv->current_audio_subpacket = 0; 776cabdff1aSopenharmony_ci viv->n_audio_subpackets = 0; 777cabdff1aSopenharmony_ci // most problematic part: guess audio offset 778cabdff1aSopenharmony_ci viv->audio_sample = av_rescale_q(viv->sb_blocks[i].packet_offset, 779cabdff1aSopenharmony_ci av_make_q(par->sample_rate, 1), 780cabdff1aSopenharmony_ci av_inv_q(s->streams[0]->time_base)); 781cabdff1aSopenharmony_ci // hand-tuned 1.s a/v offset 782cabdff1aSopenharmony_ci viv->audio_sample += par->sample_rate; 783cabdff1aSopenharmony_ci } 784cabdff1aSopenharmony_ci viv->current_sb_entry = 0; 785cabdff1aSopenharmony_ci return 1; 786cabdff1aSopenharmony_ci } 787cabdff1aSopenharmony_ci } 788cabdff1aSopenharmony_ci return 0; 789cabdff1aSopenharmony_ci} 790cabdff1aSopenharmony_ci 791cabdff1aSopenharmony_ciconst AVInputFormat ff_vividas_demuxer = { 792cabdff1aSopenharmony_ci .name = "vividas", 793cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("Vividas VIV"), 794cabdff1aSopenharmony_ci .priv_data_size = sizeof(VividasDemuxContext), 795cabdff1aSopenharmony_ci .flags_internal = FF_FMT_INIT_CLEANUP, 796cabdff1aSopenharmony_ci .read_probe = viv_probe, 797cabdff1aSopenharmony_ci .read_header = viv_read_header, 798cabdff1aSopenharmony_ci .read_packet = viv_read_packet, 799cabdff1aSopenharmony_ci .read_close = viv_read_close, 800cabdff1aSopenharmony_ci .read_seek = viv_read_seek, 801cabdff1aSopenharmony_ci}; 802