xref: /third_party/ffmpeg/libavformat/idcin.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * id Quake II CIN File Demuxer
3cabdff1aSopenharmony_ci * Copyright (c) 2003 The FFmpeg project
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/**
23cabdff1aSopenharmony_ci * @file
24cabdff1aSopenharmony_ci * id Quake II CIN file demuxer by Mike Melanson (melanson@pcisys.net)
25cabdff1aSopenharmony_ci * For more information about the id CIN format, visit:
26cabdff1aSopenharmony_ci *   http://www.csse.monash.edu.au/~timf/
27cabdff1aSopenharmony_ci *
28cabdff1aSopenharmony_ci * CIN is a somewhat quirky and ill-defined format. Here are some notes
29cabdff1aSopenharmony_ci * for anyone trying to understand the technical details of this format:
30cabdff1aSopenharmony_ci *
31cabdff1aSopenharmony_ci * The format has no definite file signature. This is problematic for a
32cabdff1aSopenharmony_ci * general-purpose media player that wants to automatically detect file
33cabdff1aSopenharmony_ci * types. However, a CIN file does start with 5 32-bit numbers that
34cabdff1aSopenharmony_ci * specify audio and video parameters. This demuxer gets around the lack
35cabdff1aSopenharmony_ci * of file signature by performing sanity checks on those parameters.
36cabdff1aSopenharmony_ci * Probabilistically, this is a reasonable solution since the number of
37cabdff1aSopenharmony_ci * valid combinations of the 5 parameters is a very small subset of the
38cabdff1aSopenharmony_ci * total 160-bit number space.
39cabdff1aSopenharmony_ci *
40cabdff1aSopenharmony_ci * Refer to the function idcin_probe() for the precise A/V parameters
41cabdff1aSopenharmony_ci * that this demuxer allows.
42cabdff1aSopenharmony_ci *
43cabdff1aSopenharmony_ci * Next, each audio and video frame has a duration of 1/14 sec. If the
44cabdff1aSopenharmony_ci * audio sample rate is a multiple of the common frequency 22050 Hz it will
45cabdff1aSopenharmony_ci * divide evenly by 14. However, if the sample rate is 11025 Hz:
46cabdff1aSopenharmony_ci *   11025 (samples/sec) / 14 (frames/sec) = 787.5 (samples/frame)
47cabdff1aSopenharmony_ci * The way the CIN stores audio in this case is by storing 787 sample
48cabdff1aSopenharmony_ci * frames in the first audio frame and 788 sample frames in the second
49cabdff1aSopenharmony_ci * audio frame. Therefore, the total number of bytes in an audio frame
50cabdff1aSopenharmony_ci * is given as:
51cabdff1aSopenharmony_ci *   audio frame #0: 787 * (bytes/sample) * (# channels) bytes in frame
52cabdff1aSopenharmony_ci *   audio frame #1: 788 * (bytes/sample) * (# channels) bytes in frame
53cabdff1aSopenharmony_ci *   audio frame #2: 787 * (bytes/sample) * (# channels) bytes in frame
54cabdff1aSopenharmony_ci *   audio frame #3: 788 * (bytes/sample) * (# channels) bytes in frame
55cabdff1aSopenharmony_ci *
56cabdff1aSopenharmony_ci * Finally, not all id CIN creation tools agree on the resolution of the
57cabdff1aSopenharmony_ci * color palette, apparently. Some creation tools specify red, green, and
58cabdff1aSopenharmony_ci * blue palette components in terms of 6-bit VGA color DAC values which
59cabdff1aSopenharmony_ci * range from 0..63. Other tools specify the RGB components as full 8-bit
60cabdff1aSopenharmony_ci * values that range from 0..255. Since there are no markers in the file to
61cabdff1aSopenharmony_ci * differentiate between the two variants, this demuxer uses the following
62cabdff1aSopenharmony_ci * heuristic:
63cabdff1aSopenharmony_ci *   - load the 768 palette bytes from disk
64cabdff1aSopenharmony_ci *   - assume that they will need to be shifted left by 2 bits to
65cabdff1aSopenharmony_ci *     transform them from 6-bit values to 8-bit values
66cabdff1aSopenharmony_ci *   - scan through all 768 palette bytes
67cabdff1aSopenharmony_ci *     - if any bytes exceed 63, do not shift the bytes at all before
68cabdff1aSopenharmony_ci *       transmitting them to the video decoder
69cabdff1aSopenharmony_ci */
70cabdff1aSopenharmony_ci
71cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
72cabdff1aSopenharmony_ci#include "libavutil/imgutils.h"
73cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
74cabdff1aSopenharmony_ci#include "avformat.h"
75cabdff1aSopenharmony_ci#include "demux.h"
76cabdff1aSopenharmony_ci#include "internal.h"
77cabdff1aSopenharmony_ci
78cabdff1aSopenharmony_ci#define HUFFMAN_TABLE_SIZE (64 * 1024)
79cabdff1aSopenharmony_ci#define IDCIN_FPS 14
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_citypedef struct IdcinDemuxContext {
82cabdff1aSopenharmony_ci    int video_stream_index;
83cabdff1aSopenharmony_ci    int audio_stream_index;
84cabdff1aSopenharmony_ci    int audio_chunk_size1;
85cabdff1aSopenharmony_ci    int audio_chunk_size2;
86cabdff1aSopenharmony_ci    int block_align;
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci    /* demux state variables */
89cabdff1aSopenharmony_ci    int current_audio_chunk;
90cabdff1aSopenharmony_ci    int next_chunk_is_video;
91cabdff1aSopenharmony_ci    int audio_present;
92cabdff1aSopenharmony_ci    int64_t first_pkt_pos;
93cabdff1aSopenharmony_ci} IdcinDemuxContext;
94cabdff1aSopenharmony_ci
95cabdff1aSopenharmony_cistatic int idcin_probe(const AVProbeData *p)
96cabdff1aSopenharmony_ci{
97cabdff1aSopenharmony_ci    unsigned int number, sample_rate;
98cabdff1aSopenharmony_ci    unsigned int w, h;
99cabdff1aSopenharmony_ci    int i;
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_ci    /*
102cabdff1aSopenharmony_ci     * This is what you could call a "probabilistic" file check: id CIN
103cabdff1aSopenharmony_ci     * files don't have a definite file signature. In lieu of such a marker,
104cabdff1aSopenharmony_ci     * perform sanity checks on the 5 32-bit header fields:
105cabdff1aSopenharmony_ci     *  width, height: greater than 0, less than or equal to 1024
106cabdff1aSopenharmony_ci     * audio sample rate: greater than or equal to 8000, less than or
107cabdff1aSopenharmony_ci     *  equal to 48000, or 0 for no audio
108cabdff1aSopenharmony_ci     * audio sample width (bytes/sample): 0 for no audio, or 1 or 2
109cabdff1aSopenharmony_ci     * audio channels: 0 for no audio, or 1 or 2
110cabdff1aSopenharmony_ci     */
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_ci    /* check we have enough data to do all checks, otherwise the
113cabdff1aSopenharmony_ci       0-padding may cause a wrong recognition */
114cabdff1aSopenharmony_ci    if (p->buf_size < 20 + HUFFMAN_TABLE_SIZE + 12)
115cabdff1aSopenharmony_ci        return 0;
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci    /* check the video width */
118cabdff1aSopenharmony_ci    w = AV_RL32(&p->buf[0]);
119cabdff1aSopenharmony_ci    if ((w == 0) || (w > 1024))
120cabdff1aSopenharmony_ci       return 0;
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    /* check the video height */
123cabdff1aSopenharmony_ci    h = AV_RL32(&p->buf[4]);
124cabdff1aSopenharmony_ci    if ((h == 0) || (h > 1024))
125cabdff1aSopenharmony_ci       return 0;
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_ci    /* check the audio sample rate */
128cabdff1aSopenharmony_ci    sample_rate = AV_RL32(&p->buf[8]);
129cabdff1aSopenharmony_ci    if (sample_rate && (sample_rate < 8000 || sample_rate > 48000))
130cabdff1aSopenharmony_ci        return 0;
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_ci    /* check the audio bytes/sample */
133cabdff1aSopenharmony_ci    number = AV_RL32(&p->buf[12]);
134cabdff1aSopenharmony_ci    if (number > 2 || sample_rate && !number)
135cabdff1aSopenharmony_ci        return 0;
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_ci    /* check the audio channels */
138cabdff1aSopenharmony_ci    number = AV_RL32(&p->buf[16]);
139cabdff1aSopenharmony_ci    if (number > 2 || sample_rate && !number)
140cabdff1aSopenharmony_ci        return 0;
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci    i = 20 + HUFFMAN_TABLE_SIZE;
143cabdff1aSopenharmony_ci    if (AV_RL32(&p->buf[i]) == 1)
144cabdff1aSopenharmony_ci        i += 768;
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_ci    if (i+12 > p->buf_size || AV_RL32(&p->buf[i+8]) != w*h)
147cabdff1aSopenharmony_ci        return 1;
148cabdff1aSopenharmony_ci
149cabdff1aSopenharmony_ci    /* return half certainty since this check is a bit sketchy */
150cabdff1aSopenharmony_ci    return AVPROBE_SCORE_EXTENSION;
151cabdff1aSopenharmony_ci}
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_cistatic int idcin_read_header(AVFormatContext *s)
154cabdff1aSopenharmony_ci{
155cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
156cabdff1aSopenharmony_ci    IdcinDemuxContext *idcin = s->priv_data;
157cabdff1aSopenharmony_ci    AVStream *st;
158cabdff1aSopenharmony_ci    unsigned int width, height;
159cabdff1aSopenharmony_ci    unsigned int sample_rate, bytes_per_sample, channels;
160cabdff1aSopenharmony_ci    int ret;
161cabdff1aSopenharmony_ci
162cabdff1aSopenharmony_ci    /* get the 5 header parameters */
163cabdff1aSopenharmony_ci    width = avio_rl32(pb);
164cabdff1aSopenharmony_ci    height = avio_rl32(pb);
165cabdff1aSopenharmony_ci    sample_rate = avio_rl32(pb);
166cabdff1aSopenharmony_ci    bytes_per_sample = avio_rl32(pb);
167cabdff1aSopenharmony_ci    channels = avio_rl32(pb);
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_ci    if (s->pb->eof_reached) {
170cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "incomplete header\n");
171cabdff1aSopenharmony_ci        return s->pb->error ? s->pb->error : AVERROR_EOF;
172cabdff1aSopenharmony_ci    }
173cabdff1aSopenharmony_ci
174cabdff1aSopenharmony_ci    if (av_image_check_size(width, height, 0, s) < 0)
175cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
176cabdff1aSopenharmony_ci    if (sample_rate > 0) {
177cabdff1aSopenharmony_ci        if (sample_rate < 14 || sample_rate > INT_MAX) {
178cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "invalid sample rate: %u\n", sample_rate);
179cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
180cabdff1aSopenharmony_ci        }
181cabdff1aSopenharmony_ci        if (bytes_per_sample < 1 || bytes_per_sample > 2) {
182cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "invalid bytes per sample: %u\n",
183cabdff1aSopenharmony_ci                   bytes_per_sample);
184cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
185cabdff1aSopenharmony_ci        }
186cabdff1aSopenharmony_ci        if (channels < 1 || channels > 2) {
187cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "invalid channels: %u\n", channels);
188cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
189cabdff1aSopenharmony_ci        }
190cabdff1aSopenharmony_ci        idcin->audio_present = 1;
191cabdff1aSopenharmony_ci    } else {
192cabdff1aSopenharmony_ci        /* if sample rate is 0, assume no audio */
193cabdff1aSopenharmony_ci        idcin->audio_present = 0;
194cabdff1aSopenharmony_ci    }
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_ci    st = avformat_new_stream(s, NULL);
197cabdff1aSopenharmony_ci    if (!st)
198cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
199cabdff1aSopenharmony_ci    avpriv_set_pts_info(st, 33, 1, IDCIN_FPS);
200cabdff1aSopenharmony_ci    st->start_time = 0;
201cabdff1aSopenharmony_ci    idcin->video_stream_index = st->index;
202cabdff1aSopenharmony_ci    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
203cabdff1aSopenharmony_ci    st->codecpar->codec_id = AV_CODEC_ID_IDCIN;
204cabdff1aSopenharmony_ci    st->codecpar->codec_tag = 0;  /* no fourcc */
205cabdff1aSopenharmony_ci    st->codecpar->width = width;
206cabdff1aSopenharmony_ci    st->codecpar->height = height;
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_ci    /* load up the Huffman tables into extradata */
209cabdff1aSopenharmony_ci    if ((ret = ff_get_extradata(s, st->codecpar, pb, HUFFMAN_TABLE_SIZE)) < 0)
210cabdff1aSopenharmony_ci        return ret;
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci    if (idcin->audio_present) {
213cabdff1aSopenharmony_ci        idcin->audio_present = 1;
214cabdff1aSopenharmony_ci        st = avformat_new_stream(s, NULL);
215cabdff1aSopenharmony_ci        if (!st)
216cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
217cabdff1aSopenharmony_ci        avpriv_set_pts_info(st, 63, 1, sample_rate);
218cabdff1aSopenharmony_ci        st->start_time = 0;
219cabdff1aSopenharmony_ci        idcin->audio_stream_index = st->index;
220cabdff1aSopenharmony_ci        st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
221cabdff1aSopenharmony_ci        st->codecpar->codec_tag = 1;
222cabdff1aSopenharmony_ci        av_channel_layout_default(&st->codecpar->ch_layout, channels);
223cabdff1aSopenharmony_ci        st->codecpar->sample_rate = sample_rate;
224cabdff1aSopenharmony_ci        st->codecpar->bits_per_coded_sample = bytes_per_sample * 8;
225cabdff1aSopenharmony_ci        st->codecpar->bit_rate = sample_rate * bytes_per_sample * 8 * channels;
226cabdff1aSopenharmony_ci        st->codecpar->block_align = idcin->block_align = bytes_per_sample * channels;
227cabdff1aSopenharmony_ci        if (bytes_per_sample == 1)
228cabdff1aSopenharmony_ci            st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
229cabdff1aSopenharmony_ci        else
230cabdff1aSopenharmony_ci            st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
231cabdff1aSopenharmony_ci
232cabdff1aSopenharmony_ci        if (sample_rate % 14 != 0) {
233cabdff1aSopenharmony_ci            idcin->audio_chunk_size1 = (sample_rate / 14) *
234cabdff1aSopenharmony_ci            bytes_per_sample * channels;
235cabdff1aSopenharmony_ci            idcin->audio_chunk_size2 = (sample_rate / 14 + 1) *
236cabdff1aSopenharmony_ci                bytes_per_sample * channels;
237cabdff1aSopenharmony_ci        } else {
238cabdff1aSopenharmony_ci            idcin->audio_chunk_size1 = idcin->audio_chunk_size2 =
239cabdff1aSopenharmony_ci                (sample_rate / 14) * bytes_per_sample * channels;
240cabdff1aSopenharmony_ci        }
241cabdff1aSopenharmony_ci        idcin->current_audio_chunk = 0;
242cabdff1aSopenharmony_ci    }
243cabdff1aSopenharmony_ci
244cabdff1aSopenharmony_ci    idcin->next_chunk_is_video = 1;
245cabdff1aSopenharmony_ci    idcin->first_pkt_pos = avio_tell(s->pb);
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_ci    return 0;
248cabdff1aSopenharmony_ci}
249cabdff1aSopenharmony_ci
250cabdff1aSopenharmony_cistatic int idcin_read_packet(AVFormatContext *s,
251cabdff1aSopenharmony_ci                             AVPacket *pkt)
252cabdff1aSopenharmony_ci{
253cabdff1aSopenharmony_ci    int ret;
254cabdff1aSopenharmony_ci    unsigned int command;
255cabdff1aSopenharmony_ci    unsigned int chunk_size;
256cabdff1aSopenharmony_ci    IdcinDemuxContext *idcin = s->priv_data;
257cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
258cabdff1aSopenharmony_ci    int i;
259cabdff1aSopenharmony_ci    int palette_scale;
260cabdff1aSopenharmony_ci    unsigned char r, g, b;
261cabdff1aSopenharmony_ci    unsigned char palette_buffer[768];
262cabdff1aSopenharmony_ci    uint32_t palette[256];
263cabdff1aSopenharmony_ci
264cabdff1aSopenharmony_ci    if (avio_feof(s->pb))
265cabdff1aSopenharmony_ci        return s->pb->error ? s->pb->error : AVERROR_EOF;
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci    if (idcin->next_chunk_is_video) {
268cabdff1aSopenharmony_ci        command = avio_rl32(pb);
269cabdff1aSopenharmony_ci        if (command == 2) {
270cabdff1aSopenharmony_ci            return AVERROR(EIO);
271cabdff1aSopenharmony_ci        } else if (command == 1) {
272cabdff1aSopenharmony_ci            /* trigger a palette change */
273cabdff1aSopenharmony_ci            ret = avio_read(pb, palette_buffer, 768);
274cabdff1aSopenharmony_ci            if (ret < 0) {
275cabdff1aSopenharmony_ci                return ret;
276cabdff1aSopenharmony_ci            } else if (ret != 768) {
277cabdff1aSopenharmony_ci                av_log(s, AV_LOG_ERROR, "incomplete packet\n");
278cabdff1aSopenharmony_ci                return AVERROR(EIO);
279cabdff1aSopenharmony_ci            }
280cabdff1aSopenharmony_ci            /* scale the palette as necessary */
281cabdff1aSopenharmony_ci            palette_scale = 2;
282cabdff1aSopenharmony_ci            for (i = 0; i < 768; i++)
283cabdff1aSopenharmony_ci                if (palette_buffer[i] > 63) {
284cabdff1aSopenharmony_ci                    palette_scale = 0;
285cabdff1aSopenharmony_ci                    break;
286cabdff1aSopenharmony_ci                }
287cabdff1aSopenharmony_ci
288cabdff1aSopenharmony_ci            for (i = 0; i < 256; i++) {
289cabdff1aSopenharmony_ci                r = palette_buffer[i * 3    ] << palette_scale;
290cabdff1aSopenharmony_ci                g = palette_buffer[i * 3 + 1] << palette_scale;
291cabdff1aSopenharmony_ci                b = palette_buffer[i * 3 + 2] << palette_scale;
292cabdff1aSopenharmony_ci                palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | (b);
293cabdff1aSopenharmony_ci                if (palette_scale == 2)
294cabdff1aSopenharmony_ci                    palette[i] |= palette[i] >> 6 & 0x30303;
295cabdff1aSopenharmony_ci            }
296cabdff1aSopenharmony_ci        }
297cabdff1aSopenharmony_ci
298cabdff1aSopenharmony_ci        if (s->pb->eof_reached) {
299cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "incomplete packet\n");
300cabdff1aSopenharmony_ci            return s->pb->error ? s->pb->error : AVERROR_EOF;
301cabdff1aSopenharmony_ci        }
302cabdff1aSopenharmony_ci        chunk_size = avio_rl32(pb);
303cabdff1aSopenharmony_ci        if (chunk_size < 4 || chunk_size > INT_MAX - 4) {
304cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "invalid chunk size: %u\n", chunk_size);
305cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
306cabdff1aSopenharmony_ci        }
307cabdff1aSopenharmony_ci        /* skip the number of decoded bytes (always equal to width * height) */
308cabdff1aSopenharmony_ci        avio_skip(pb, 4);
309cabdff1aSopenharmony_ci        chunk_size -= 4;
310cabdff1aSopenharmony_ci        ret= av_get_packet(pb, pkt, chunk_size);
311cabdff1aSopenharmony_ci        if (ret < 0)
312cabdff1aSopenharmony_ci            return ret;
313cabdff1aSopenharmony_ci        else if (ret != chunk_size) {
314cabdff1aSopenharmony_ci            av_log(s, AV_LOG_ERROR, "incomplete packet\n");
315cabdff1aSopenharmony_ci            return AVERROR(EIO);
316cabdff1aSopenharmony_ci        }
317cabdff1aSopenharmony_ci        if (command == 1) {
318cabdff1aSopenharmony_ci            uint8_t *pal;
319cabdff1aSopenharmony_ci
320cabdff1aSopenharmony_ci            pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE,
321cabdff1aSopenharmony_ci                                          AVPALETTE_SIZE);
322cabdff1aSopenharmony_ci            if (!pal) {
323cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
324cabdff1aSopenharmony_ci            }
325cabdff1aSopenharmony_ci            memcpy(pal, palette, AVPALETTE_SIZE);
326cabdff1aSopenharmony_ci            pkt->flags |= AV_PKT_FLAG_KEY;
327cabdff1aSopenharmony_ci        }
328cabdff1aSopenharmony_ci        pkt->stream_index = idcin->video_stream_index;
329cabdff1aSopenharmony_ci        pkt->duration     = 1;
330cabdff1aSopenharmony_ci    } else {
331cabdff1aSopenharmony_ci        /* send out the audio chunk */
332cabdff1aSopenharmony_ci        if (idcin->current_audio_chunk)
333cabdff1aSopenharmony_ci            chunk_size = idcin->audio_chunk_size2;
334cabdff1aSopenharmony_ci        else
335cabdff1aSopenharmony_ci            chunk_size = idcin->audio_chunk_size1;
336cabdff1aSopenharmony_ci        ret= av_get_packet(pb, pkt, chunk_size);
337cabdff1aSopenharmony_ci        if (ret < 0)
338cabdff1aSopenharmony_ci            return ret;
339cabdff1aSopenharmony_ci        pkt->stream_index = idcin->audio_stream_index;
340cabdff1aSopenharmony_ci        pkt->duration     = chunk_size / idcin->block_align;
341cabdff1aSopenharmony_ci
342cabdff1aSopenharmony_ci        idcin->current_audio_chunk ^= 1;
343cabdff1aSopenharmony_ci    }
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_ci    if (idcin->audio_present)
346cabdff1aSopenharmony_ci        idcin->next_chunk_is_video ^= 1;
347cabdff1aSopenharmony_ci
348cabdff1aSopenharmony_ci    return 0;
349cabdff1aSopenharmony_ci}
350cabdff1aSopenharmony_ci
351cabdff1aSopenharmony_cistatic int idcin_read_seek(AVFormatContext *s, int stream_index,
352cabdff1aSopenharmony_ci                           int64_t timestamp, int flags)
353cabdff1aSopenharmony_ci{
354cabdff1aSopenharmony_ci    IdcinDemuxContext *idcin = s->priv_data;
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    if (idcin->first_pkt_pos > 0) {
357cabdff1aSopenharmony_ci        int64_t ret = avio_seek(s->pb, idcin->first_pkt_pos, SEEK_SET);
358cabdff1aSopenharmony_ci        if (ret < 0)
359cabdff1aSopenharmony_ci            return ret;
360cabdff1aSopenharmony_ci        avpriv_update_cur_dts(s, s->streams[idcin->video_stream_index], 0);
361cabdff1aSopenharmony_ci        idcin->next_chunk_is_video = 1;
362cabdff1aSopenharmony_ci        idcin->current_audio_chunk = 0;
363cabdff1aSopenharmony_ci        return 0;
364cabdff1aSopenharmony_ci    }
365cabdff1aSopenharmony_ci    return -1;
366cabdff1aSopenharmony_ci}
367cabdff1aSopenharmony_ci
368cabdff1aSopenharmony_ciconst AVInputFormat ff_idcin_demuxer = {
369cabdff1aSopenharmony_ci    .name           = "idcin",
370cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("id Cinematic"),
371cabdff1aSopenharmony_ci    .priv_data_size = sizeof(IdcinDemuxContext),
372cabdff1aSopenharmony_ci    .read_probe     = idcin_probe,
373cabdff1aSopenharmony_ci    .read_header    = idcin_read_header,
374cabdff1aSopenharmony_ci    .read_packet    = idcin_read_packet,
375cabdff1aSopenharmony_ci    .read_seek      = idcin_read_seek,
376cabdff1aSopenharmony_ci    .flags          = AVFMT_NO_BYTE_SEEK,
377cabdff1aSopenharmony_ci};
378