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