xref: /third_party/ffmpeg/libavformat/cinedec.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Phantom Cine demuxer
3cabdff1aSopenharmony_ci * Copyright (c) 2010-2011 Peter Ross <pross@xvid.org>
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 * Phantom Cine demuxer
25cabdff1aSopenharmony_ci * @author Peter Ross <pross@xvid.org>
26cabdff1aSopenharmony_ci */
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
29cabdff1aSopenharmony_ci#include "libavcodec/bmp.h"
30cabdff1aSopenharmony_ci#include "libavutil/intfloat.h"
31cabdff1aSopenharmony_ci#include "avformat.h"
32cabdff1aSopenharmony_ci#include "internal.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_citypedef struct {
35cabdff1aSopenharmony_ci    uint64_t pts;
36cabdff1aSopenharmony_ci    uint64_t maxsize;
37cabdff1aSopenharmony_ci} CineDemuxContext;
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ci/** Compression */
40cabdff1aSopenharmony_cienum {
41cabdff1aSopenharmony_ci    CC_RGB   = 0,  /**< Gray */
42cabdff1aSopenharmony_ci    CC_LEAD  = 1,  /**< LEAD (M)JPEG */
43cabdff1aSopenharmony_ci    CC_UNINT = 2   /**< Uninterpolated color image (CFA field indicates color ordering)  */
44cabdff1aSopenharmony_ci};
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_ci/** Color Filter Array */
47cabdff1aSopenharmony_cienum {
48cabdff1aSopenharmony_ci    CFA_NONE      = 0,  /**< GRAY */
49cabdff1aSopenharmony_ci    CFA_VRI       = 1,  /**< GBRG/RGGB */
50cabdff1aSopenharmony_ci    CFA_VRIV6     = 2,  /**< BGGR/GRBG */
51cabdff1aSopenharmony_ci    CFA_BAYER     = 3,  /**< GB/RG */
52cabdff1aSopenharmony_ci    CFA_BAYERFLIP = 4,  /**< RG/GB */
53cabdff1aSopenharmony_ci};
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ci#define CFA_TLGRAY  0x80000000U
56cabdff1aSopenharmony_ci#define CFA_TRGRAY  0x40000000U
57cabdff1aSopenharmony_ci#define CFA_BLGRAY  0x20000000U
58cabdff1aSopenharmony_ci#define CFA_BRGRAY  0x10000000U
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cistatic int cine_read_probe(const AVProbeData *p)
61cabdff1aSopenharmony_ci{
62cabdff1aSopenharmony_ci    int HeaderSize;
63cabdff1aSopenharmony_ci    if (p->buf[0] == 'C' && p->buf[1] == 'I' &&  // Type
64cabdff1aSopenharmony_ci        (HeaderSize = AV_RL16(p->buf + 2)) >= 0x2C &&  // HeaderSize
65cabdff1aSopenharmony_ci        AV_RL16(p->buf + 4) <= CC_UNINT &&       // Compression
66cabdff1aSopenharmony_ci        AV_RL16(p->buf + 6) <= 1 &&              // Version
67cabdff1aSopenharmony_ci        AV_RL32(p->buf + 20) &&                  // ImageCount
68cabdff1aSopenharmony_ci        AV_RL32(p->buf + 24) >= HeaderSize &&    // OffImageHeader
69cabdff1aSopenharmony_ci        AV_RL32(p->buf + 28) >= HeaderSize &&    // OffSetup
70cabdff1aSopenharmony_ci        AV_RL32(p->buf + 32) >= HeaderSize)      // OffImageOffsets
71cabdff1aSopenharmony_ci        return AVPROBE_SCORE_MAX;
72cabdff1aSopenharmony_ci    return 0;
73cabdff1aSopenharmony_ci}
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_cistatic int set_metadata_int(AVDictionary **dict, const char *key, int value, int allow_zero)
76cabdff1aSopenharmony_ci{
77cabdff1aSopenharmony_ci    if (value || allow_zero) {
78cabdff1aSopenharmony_ci        return av_dict_set_int(dict, key, value, 0);
79cabdff1aSopenharmony_ci    }
80cabdff1aSopenharmony_ci    return 0;
81cabdff1aSopenharmony_ci}
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_cistatic int set_metadata_float(AVDictionary **dict, const char *key, float value, int allow_zero)
84cabdff1aSopenharmony_ci{
85cabdff1aSopenharmony_ci    if (value != 0 || allow_zero) {
86cabdff1aSopenharmony_ci        char tmp[64];
87cabdff1aSopenharmony_ci        snprintf(tmp, sizeof(tmp), "%f", value);
88cabdff1aSopenharmony_ci        return av_dict_set(dict, key, tmp, 0);
89cabdff1aSopenharmony_ci    }
90cabdff1aSopenharmony_ci    return 0;
91cabdff1aSopenharmony_ci}
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_cistatic int cine_read_header(AVFormatContext *avctx)
94cabdff1aSopenharmony_ci{
95cabdff1aSopenharmony_ci    AVIOContext *pb = avctx->pb;
96cabdff1aSopenharmony_ci    AVStream *st;
97cabdff1aSopenharmony_ci    unsigned int version, compression, offImageHeader, offSetup, offImageOffsets, biBitCount, length, CFA;
98cabdff1aSopenharmony_ci    int vflip;
99cabdff1aSopenharmony_ci    char *description;
100cabdff1aSopenharmony_ci    uint64_t i;
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci    st = avformat_new_stream(avctx, NULL);
103cabdff1aSopenharmony_ci    if (!st)
104cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
105cabdff1aSopenharmony_ci    st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
106cabdff1aSopenharmony_ci    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
107cabdff1aSopenharmony_ci    st->codecpar->codec_tag  = 0;
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_ci    /* CINEFILEHEADER structure */
110cabdff1aSopenharmony_ci    avio_skip(pb, 4); // Type, Headersize
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_ci    compression = avio_rl16(pb);
113cabdff1aSopenharmony_ci    version     = avio_rl16(pb);
114cabdff1aSopenharmony_ci    if (version != 1) {
115cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "unknown version %i", version);
116cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
117cabdff1aSopenharmony_ci    }
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    avio_skip(pb, 12); // FirstMovieImage, TotalImageCount, FirstImageNumber
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    st->duration    = avio_rl32(pb);
122cabdff1aSopenharmony_ci    offImageHeader  = avio_rl32(pb);
123cabdff1aSopenharmony_ci    offSetup        = avio_rl32(pb);
124cabdff1aSopenharmony_ci    offImageOffsets = avio_rl32(pb);
125cabdff1aSopenharmony_ci
126cabdff1aSopenharmony_ci    avio_skip(pb, 8); // TriggerTime
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci    /* BITMAPINFOHEADER structure */
129cabdff1aSopenharmony_ci    avio_seek(pb, offImageHeader, SEEK_SET);
130cabdff1aSopenharmony_ci    avio_skip(pb, 4); //biSize
131cabdff1aSopenharmony_ci    st->codecpar->width      = avio_rl32(pb);
132cabdff1aSopenharmony_ci    st->codecpar->height     = avio_rl32(pb);
133cabdff1aSopenharmony_ci
134cabdff1aSopenharmony_ci    if (avio_rl16(pb) != 1) // biPlanes
135cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_ci    biBitCount = avio_rl16(pb);
138cabdff1aSopenharmony_ci    if (biBitCount != 8 && biBitCount != 16 && biBitCount != 24 && biBitCount != 48) {
139cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
140cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
141cabdff1aSopenharmony_ci    }
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci    switch (avio_rl32(pb)) {
144cabdff1aSopenharmony_ci    case BMP_RGB:
145cabdff1aSopenharmony_ci        vflip = 0;
146cabdff1aSopenharmony_ci        break;
147cabdff1aSopenharmony_ci    case 0x100: /* BI_PACKED */
148cabdff1aSopenharmony_ci        st->codecpar->codec_tag = MKTAG('B', 'I', 'T', 0);
149cabdff1aSopenharmony_ci        vflip = 1;
150cabdff1aSopenharmony_ci        break;
151cabdff1aSopenharmony_ci    default:
152cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "unknown bitmap compression");
153cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
154cabdff1aSopenharmony_ci    }
155cabdff1aSopenharmony_ci
156cabdff1aSopenharmony_ci    avio_skip(pb, 4); // biSizeImage
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    /* parse SETUP structure */
159cabdff1aSopenharmony_ci    avio_seek(pb, offSetup, SEEK_SET);
160cabdff1aSopenharmony_ci    avio_skip(pb, 140); // FrameRatae16 .. descriptionOld
161cabdff1aSopenharmony_ci    if (avio_rl16(pb) != 0x5453)
162cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
163cabdff1aSopenharmony_ci    length = avio_rl16(pb);
164cabdff1aSopenharmony_ci    if (length < 0x163C) {
165cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "short SETUP header");
166cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
167cabdff1aSopenharmony_ci    }
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_ci    avio_skip(pb, 616); // Binning .. bFlipH
170cabdff1aSopenharmony_ci    if (!avio_rl32(pb) ^ vflip) {
171cabdff1aSopenharmony_ci        st->codecpar->extradata  = av_strdup("BottomUp");
172cabdff1aSopenharmony_ci        if (!st->codecpar->extradata) {
173cabdff1aSopenharmony_ci            st->codecpar->extradata_size = 0;
174cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
175cabdff1aSopenharmony_ci        }
176cabdff1aSopenharmony_ci        st->codecpar->extradata_size  = 9;
177cabdff1aSopenharmony_ci    }
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci    avio_skip(pb, 4); // Grid
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci    avpriv_set_pts_info(st, 64, 1, avio_rl32(pb));
182cabdff1aSopenharmony_ci
183cabdff1aSopenharmony_ci    avio_skip(pb, 20); // Shutter .. bEnableColor
184cabdff1aSopenharmony_ci
185cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "camera_version", avio_rl32(pb), 0);
186cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "firmware_version", avio_rl32(pb), 0);
187cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "software_version", avio_rl32(pb), 0);
188cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "recording_timezone", avio_rl32(pb), 0);
189cabdff1aSopenharmony_ci
190cabdff1aSopenharmony_ci    CFA = avio_rl32(pb);
191cabdff1aSopenharmony_ci
192cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "brightness", avio_rl32(pb), 1);
193cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "contrast", avio_rl32(pb), 1);
194cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "gamma", avio_rl32(pb), 1);
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_ci    avio_skip(pb, 12 + 16); // Reserved1 .. AutoExpRect
197cabdff1aSopenharmony_ci    set_metadata_float(&st->metadata, "wbgain[0].r", av_int2float(avio_rl32(pb)), 1);
198cabdff1aSopenharmony_ci    set_metadata_float(&st->metadata, "wbgain[0].b", av_int2float(avio_rl32(pb)), 1);
199cabdff1aSopenharmony_ci    avio_skip(pb, 36); // WBGain[1].. WBView
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ci    st->codecpar->bits_per_coded_sample = avio_rl32(pb);
202cabdff1aSopenharmony_ci
203cabdff1aSopenharmony_ci    if (compression == CC_RGB) {
204cabdff1aSopenharmony_ci        if (biBitCount == 8) {
205cabdff1aSopenharmony_ci            st->codecpar->format = AV_PIX_FMT_GRAY8;
206cabdff1aSopenharmony_ci        } else if (biBitCount == 16) {
207cabdff1aSopenharmony_ci            st->codecpar->format = AV_PIX_FMT_GRAY16LE;
208cabdff1aSopenharmony_ci        } else if (biBitCount == 24) {
209cabdff1aSopenharmony_ci            st->codecpar->format = AV_PIX_FMT_BGR24;
210cabdff1aSopenharmony_ci        } else if (biBitCount == 48) {
211cabdff1aSopenharmony_ci            st->codecpar->format = AV_PIX_FMT_BGR48LE;
212cabdff1aSopenharmony_ci        } else {
213cabdff1aSopenharmony_ci            avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
214cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
215cabdff1aSopenharmony_ci        }
216cabdff1aSopenharmony_ci    } else if (compression == CC_UNINT) {
217cabdff1aSopenharmony_ci        switch (CFA & 0xFFFFFF) {
218cabdff1aSopenharmony_ci        case CFA_BAYER:
219cabdff1aSopenharmony_ci            if (biBitCount == 8) {
220cabdff1aSopenharmony_ci                st->codecpar->format = AV_PIX_FMT_BAYER_GBRG8;
221cabdff1aSopenharmony_ci            } else if (biBitCount == 16) {
222cabdff1aSopenharmony_ci                st->codecpar->format = AV_PIX_FMT_BAYER_GBRG16LE;
223cabdff1aSopenharmony_ci            } else {
224cabdff1aSopenharmony_ci                avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
225cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
226cabdff1aSopenharmony_ci            }
227cabdff1aSopenharmony_ci            break;
228cabdff1aSopenharmony_ci        case CFA_BAYERFLIP:
229cabdff1aSopenharmony_ci            if (biBitCount == 8) {
230cabdff1aSopenharmony_ci                st->codecpar->format = AV_PIX_FMT_BAYER_RGGB8;
231cabdff1aSopenharmony_ci            } else if (biBitCount == 16) {
232cabdff1aSopenharmony_ci                st->codecpar->format = AV_PIX_FMT_BAYER_RGGB16LE;
233cabdff1aSopenharmony_ci            } else {
234cabdff1aSopenharmony_ci                avpriv_request_sample(avctx, "unsupported biBitCount %i", biBitCount);
235cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
236cabdff1aSopenharmony_ci            }
237cabdff1aSopenharmony_ci            break;
238cabdff1aSopenharmony_ci        default:
239cabdff1aSopenharmony_ci           avpriv_request_sample(avctx, "unsupported Color Field Array (CFA) %i", CFA & 0xFFFFFF);
240cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
241cabdff1aSopenharmony_ci        }
242cabdff1aSopenharmony_ci    } else { //CC_LEAD
243cabdff1aSopenharmony_ci        avpriv_request_sample(avctx, "unsupported compression %i", compression);
244cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
245cabdff1aSopenharmony_ci    }
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_ci    avio_skip(pb, 668); // Conv8Min ... Sensor
248cabdff1aSopenharmony_ci
249cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "shutter_ns", avio_rl32(pb), 0);
250cabdff1aSopenharmony_ci
251cabdff1aSopenharmony_ci    avio_skip(pb, 24); // EDRShutterNs ... ImHeightAcq
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci#define DESCRIPTION_SIZE 4096
254cabdff1aSopenharmony_ci    description = av_malloc(DESCRIPTION_SIZE + 1);
255cabdff1aSopenharmony_ci    if (!description)
256cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
257cabdff1aSopenharmony_ci    i = avio_get_str(pb, DESCRIPTION_SIZE, description, DESCRIPTION_SIZE + 1);
258cabdff1aSopenharmony_ci    if (i < DESCRIPTION_SIZE)
259cabdff1aSopenharmony_ci        avio_skip(pb, DESCRIPTION_SIZE - i);
260cabdff1aSopenharmony_ci    if (description[0])
261cabdff1aSopenharmony_ci        av_dict_set(&st->metadata, "description", description, AV_DICT_DONT_STRDUP_VAL);
262cabdff1aSopenharmony_ci    else
263cabdff1aSopenharmony_ci        av_free(description);
264cabdff1aSopenharmony_ci
265cabdff1aSopenharmony_ci    avio_skip(pb, 1176); // RisingEdge ... cmUser
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "enable_crop", avio_rl32(pb), 1);
268cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "crop_left", avio_rl32(pb), 1);
269cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "crop_top", avio_rl32(pb), 1);
270cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "crop_right", avio_rl32(pb), 1);
271cabdff1aSopenharmony_ci    set_metadata_int(&st->metadata, "crop_bottom", avio_rl32(pb), 1);
272cabdff1aSopenharmony_ci
273cabdff1aSopenharmony_ci    /* parse image offsets */
274cabdff1aSopenharmony_ci    avio_seek(pb, offImageOffsets, SEEK_SET);
275cabdff1aSopenharmony_ci    for (i = 0; i < st->duration; i++) {
276cabdff1aSopenharmony_ci        int64_t pos = avio_rl64(pb);
277cabdff1aSopenharmony_ci        if (avio_feof(pb) || pos < 0)
278cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
279cabdff1aSopenharmony_ci
280cabdff1aSopenharmony_ci        av_add_index_entry(st, pos, i, 0, 0, AVINDEX_KEYFRAME);
281cabdff1aSopenharmony_ci    }
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci    return 0;
284cabdff1aSopenharmony_ci}
285cabdff1aSopenharmony_ci
286cabdff1aSopenharmony_cistatic int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt)
287cabdff1aSopenharmony_ci{
288cabdff1aSopenharmony_ci    CineDemuxContext *cine = avctx->priv_data;
289cabdff1aSopenharmony_ci    AVStream *st = avctx->streams[0];
290cabdff1aSopenharmony_ci    FFStream *const sti = ffstream(st);
291cabdff1aSopenharmony_ci    AVIOContext *pb = avctx->pb;
292cabdff1aSopenharmony_ci    int n, size, ret;
293cabdff1aSopenharmony_ci    int64_t ret64;
294cabdff1aSopenharmony_ci
295cabdff1aSopenharmony_ci    if (cine->pts >= sti->nb_index_entries)
296cabdff1aSopenharmony_ci        return AVERROR_EOF;
297cabdff1aSopenharmony_ci
298cabdff1aSopenharmony_ci    ret64 = avio_seek(pb, sti->index_entries[cine->pts].pos, SEEK_SET);
299cabdff1aSopenharmony_ci    if (ret64 < 0)
300cabdff1aSopenharmony_ci        return ret64;
301cabdff1aSopenharmony_ci    n = avio_rl32(pb);
302cabdff1aSopenharmony_ci    if (n < 8)
303cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
304cabdff1aSopenharmony_ci    avio_skip(pb, n - 8);
305cabdff1aSopenharmony_ci    size = avio_rl32(pb);
306cabdff1aSopenharmony_ci    if (avio_feof(pb) || size < 0)
307cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
308cabdff1aSopenharmony_ci
309cabdff1aSopenharmony_ci    if (cine->maxsize && (uint64_t)sti->index_entries[cine->pts].pos + size + n > cine->maxsize)
310cabdff1aSopenharmony_ci        size = cine->maxsize - sti->index_entries[cine->pts].pos - n;
311cabdff1aSopenharmony_ci
312cabdff1aSopenharmony_ci    ret = av_get_packet(pb, pkt, size);
313cabdff1aSopenharmony_ci    if (ret < 0)
314cabdff1aSopenharmony_ci        return ret;
315cabdff1aSopenharmony_ci
316cabdff1aSopenharmony_ci    if (ret != size)
317cabdff1aSopenharmony_ci        cine->maxsize = (uint64_t)sti->index_entries[cine->pts].pos + n + ret;
318cabdff1aSopenharmony_ci
319cabdff1aSopenharmony_ci    pkt->pts = cine->pts++;
320cabdff1aSopenharmony_ci    pkt->stream_index = 0;
321cabdff1aSopenharmony_ci    pkt->flags |= AV_PKT_FLAG_KEY;
322cabdff1aSopenharmony_ci    return 0;
323cabdff1aSopenharmony_ci}
324cabdff1aSopenharmony_ci
325cabdff1aSopenharmony_cistatic int cine_read_seek(AVFormatContext *avctx, int stream_index, int64_t timestamp, int flags)
326cabdff1aSopenharmony_ci{
327cabdff1aSopenharmony_ci    CineDemuxContext *cine = avctx->priv_data;
328cabdff1aSopenharmony_ci
329cabdff1aSopenharmony_ci    if ((flags & AVSEEK_FLAG_FRAME) || (flags & AVSEEK_FLAG_BYTE))
330cabdff1aSopenharmony_ci        return AVERROR(ENOSYS);
331cabdff1aSopenharmony_ci
332cabdff1aSopenharmony_ci    if (!(avctx->pb->seekable & AVIO_SEEKABLE_NORMAL))
333cabdff1aSopenharmony_ci        return AVERROR(EIO);
334cabdff1aSopenharmony_ci
335cabdff1aSopenharmony_ci    cine->pts = timestamp;
336cabdff1aSopenharmony_ci    return 0;
337cabdff1aSopenharmony_ci}
338cabdff1aSopenharmony_ci
339cabdff1aSopenharmony_ciconst AVInputFormat ff_cine_demuxer = {
340cabdff1aSopenharmony_ci    .name           = "cine",
341cabdff1aSopenharmony_ci    .long_name      = NULL_IF_CONFIG_SMALL("Phantom Cine"),
342cabdff1aSopenharmony_ci    .priv_data_size = sizeof(CineDemuxContext),
343cabdff1aSopenharmony_ci    .read_probe     = cine_read_probe,
344cabdff1aSopenharmony_ci    .read_header    = cine_read_header,
345cabdff1aSopenharmony_ci    .read_packet    = cine_read_packet,
346cabdff1aSopenharmony_ci    .read_seek      = cine_read_seek,
347cabdff1aSopenharmony_ci};
348