1cabdff1aSopenharmony_ci/**
2cabdff1aSopenharmony_ci    Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
3cabdff1aSopenharmony_ci
4cabdff1aSopenharmony_ci    Permission is hereby granted, free of charge, to any person
5cabdff1aSopenharmony_ci    obtaining a copy of this software and associated documentation
6cabdff1aSopenharmony_ci    files (the "Software"), to deal in the Software without
7cabdff1aSopenharmony_ci    restriction, including without limitation the rights to use, copy,
8cabdff1aSopenharmony_ci    modify, merge, publish, distribute, sublicense, and/or sell copies
9cabdff1aSopenharmony_ci    of the Software, and to permit persons to whom the Software is
10cabdff1aSopenharmony_ci    furnished to do so, subject to the following conditions:
11cabdff1aSopenharmony_ci
12cabdff1aSopenharmony_ci    The above copyright notice and this permission notice shall be
13cabdff1aSopenharmony_ci    included in all copies or substantial portions of the Software.
14cabdff1aSopenharmony_ci
15cabdff1aSopenharmony_ci    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16cabdff1aSopenharmony_ci    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17cabdff1aSopenharmony_ci    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18cabdff1aSopenharmony_ci    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19cabdff1aSopenharmony_ci    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20cabdff1aSopenharmony_ci    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21cabdff1aSopenharmony_ci    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22cabdff1aSopenharmony_ci    DEALINGS IN THE SOFTWARE.
23cabdff1aSopenharmony_ci**/
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci#ifndef AVFORMAT_OGGDEC_H
26cabdff1aSopenharmony_ci#define AVFORMAT_OGGDEC_H
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#include "avformat.h"
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_cistruct ogg_codec {
31cabdff1aSopenharmony_ci    const int8_t *magic;
32cabdff1aSopenharmony_ci    uint8_t magicsize;
33cabdff1aSopenharmony_ci    const int8_t *name;
34cabdff1aSopenharmony_ci    /**
35cabdff1aSopenharmony_ci     * Attempt to process a packet as a header
36cabdff1aSopenharmony_ci     * @return 1 if the packet was a valid header,
37cabdff1aSopenharmony_ci     *         0 if the packet was not a header (was a data packet)
38cabdff1aSopenharmony_ci     *         -1 if an error occurred or for unsupported stream
39cabdff1aSopenharmony_ci     */
40cabdff1aSopenharmony_ci    int (*header)(AVFormatContext *, int);
41cabdff1aSopenharmony_ci    int (*packet)(AVFormatContext *, int);
42cabdff1aSopenharmony_ci    /**
43cabdff1aSopenharmony_ci     * Translate a granule into a timestamp.
44cabdff1aSopenharmony_ci     * Will set dts if non-null and known.
45cabdff1aSopenharmony_ci     * @return pts
46cabdff1aSopenharmony_ci     */
47cabdff1aSopenharmony_ci    uint64_t (*gptopts)(AVFormatContext *, int, uint64_t, int64_t *dts);
48cabdff1aSopenharmony_ci    /**
49cabdff1aSopenharmony_ci     * 1 if granule is the start time of the associated packet.
50cabdff1aSopenharmony_ci     * 0 if granule is the end time of the associated packet.
51cabdff1aSopenharmony_ci     */
52cabdff1aSopenharmony_ci    int granule_is_start;
53cabdff1aSopenharmony_ci    /**
54cabdff1aSopenharmony_ci     * Number of expected headers
55cabdff1aSopenharmony_ci     */
56cabdff1aSopenharmony_ci    int nb_header;
57cabdff1aSopenharmony_ci    void (*cleanup)(AVFormatContext *s, int idx);
58cabdff1aSopenharmony_ci};
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cistruct ogg_stream {
61cabdff1aSopenharmony_ci    uint8_t *buf;
62cabdff1aSopenharmony_ci    unsigned int bufsize;
63cabdff1aSopenharmony_ci    unsigned int bufpos;
64cabdff1aSopenharmony_ci    unsigned int pstart;
65cabdff1aSopenharmony_ci    unsigned int psize;
66cabdff1aSopenharmony_ci    unsigned int pflags;
67cabdff1aSopenharmony_ci    unsigned int pduration;
68cabdff1aSopenharmony_ci    uint32_t serial;
69cabdff1aSopenharmony_ci    uint64_t granule;
70cabdff1aSopenharmony_ci    uint64_t start_granule;
71cabdff1aSopenharmony_ci    int64_t lastpts;
72cabdff1aSopenharmony_ci    int64_t lastdts;
73cabdff1aSopenharmony_ci    int64_t sync_pos;   ///< file offset of the first page needed to reconstruct the current packet
74cabdff1aSopenharmony_ci    int64_t page_pos;   ///< file offset of the current page
75cabdff1aSopenharmony_ci    int flags;
76cabdff1aSopenharmony_ci    const struct ogg_codec *codec;
77cabdff1aSopenharmony_ci    int header;
78cabdff1aSopenharmony_ci    int nsegs, segp;
79cabdff1aSopenharmony_ci    uint8_t segments[255];
80cabdff1aSopenharmony_ci    int incomplete; ///< whether we're expecting a continuation in the next page
81cabdff1aSopenharmony_ci    int page_end;   ///< current packet is the last one completed in the page
82cabdff1aSopenharmony_ci    int keyframe_seek;
83cabdff1aSopenharmony_ci    int got_start;
84cabdff1aSopenharmony_ci    int got_data;   ///< 1 if the stream got some data (non-initial packets), 0 otherwise
85cabdff1aSopenharmony_ci    int nb_header; ///< set to the number of parsed headers
86cabdff1aSopenharmony_ci    int start_trimming; ///< set the number of packets to drop from the start
87cabdff1aSopenharmony_ci    int end_trimming; ///< set the number of packets to drop from the end
88cabdff1aSopenharmony_ci    uint8_t *new_metadata;
89cabdff1aSopenharmony_ci    size_t new_metadata_size;
90cabdff1aSopenharmony_ci    void *private;
91cabdff1aSopenharmony_ci};
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_cistruct ogg_state {
94cabdff1aSopenharmony_ci    uint64_t pos;
95cabdff1aSopenharmony_ci    int curidx;
96cabdff1aSopenharmony_ci    struct ogg_state *next;
97cabdff1aSopenharmony_ci    int nstreams;
98cabdff1aSopenharmony_ci    struct ogg_stream streams[1];
99cabdff1aSopenharmony_ci};
100cabdff1aSopenharmony_ci
101cabdff1aSopenharmony_cistruct ogg {
102cabdff1aSopenharmony_ci    struct ogg_stream *streams;
103cabdff1aSopenharmony_ci    int nstreams;
104cabdff1aSopenharmony_ci    int headers;
105cabdff1aSopenharmony_ci    int curidx;
106cabdff1aSopenharmony_ci    int64_t page_pos;                   ///< file offset of the current page
107cabdff1aSopenharmony_ci    struct ogg_state *state;
108cabdff1aSopenharmony_ci};
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci#define OGG_FLAG_CONT 1
111cabdff1aSopenharmony_ci#define OGG_FLAG_BOS  2
112cabdff1aSopenharmony_ci#define OGG_FLAG_EOS  4
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci#define OGG_NOGRANULE_VALUE (-1ull)
115cabdff1aSopenharmony_ci
116cabdff1aSopenharmony_ciextern const struct ogg_codec ff_celt_codec;
117cabdff1aSopenharmony_ciextern const struct ogg_codec ff_dirac_codec;
118cabdff1aSopenharmony_ciextern const struct ogg_codec ff_flac_codec;
119cabdff1aSopenharmony_ciextern const struct ogg_codec ff_ogm_audio_codec;
120cabdff1aSopenharmony_ciextern const struct ogg_codec ff_ogm_old_codec;
121cabdff1aSopenharmony_ciextern const struct ogg_codec ff_ogm_text_codec;
122cabdff1aSopenharmony_ciextern const struct ogg_codec ff_ogm_video_codec;
123cabdff1aSopenharmony_ciextern const struct ogg_codec ff_old_dirac_codec;
124cabdff1aSopenharmony_ciextern const struct ogg_codec ff_old_flac_codec;
125cabdff1aSopenharmony_ciextern const struct ogg_codec ff_opus_codec;
126cabdff1aSopenharmony_ciextern const struct ogg_codec ff_skeleton_codec;
127cabdff1aSopenharmony_ciextern const struct ogg_codec ff_speex_codec;
128cabdff1aSopenharmony_ciextern const struct ogg_codec ff_theora_codec;
129cabdff1aSopenharmony_ciextern const struct ogg_codec ff_vorbis_codec;
130cabdff1aSopenharmony_ciextern const struct ogg_codec ff_vp8_codec;
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_ci/**
133cabdff1aSopenharmony_ci * Parse Vorbis comments
134cabdff1aSopenharmony_ci *
135cabdff1aSopenharmony_ci * @note  The buffer will be temporarily modifed by this function,
136cabdff1aSopenharmony_ci *        so it needs to be writable. Furthermore it must be padded
137cabdff1aSopenharmony_ci *        by a single byte (not counted in size).
138cabdff1aSopenharmony_ci *        All changes will have been reverted upon return.
139cabdff1aSopenharmony_ci */
140cabdff1aSopenharmony_ciint ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m,
141cabdff1aSopenharmony_ci                      const uint8_t *buf, int size, int parse_picture);
142cabdff1aSopenharmony_ci
143cabdff1aSopenharmony_ci/**
144cabdff1aSopenharmony_ci * Parse Vorbis comments and add metadata to an AVStream
145cabdff1aSopenharmony_ci *
146cabdff1aSopenharmony_ci * @note  The buffer will be temporarily modifed by this function,
147cabdff1aSopenharmony_ci *        so it needs to be writable. Furthermore it must be padded
148cabdff1aSopenharmony_ci *        by a single byte (not counted in size).
149cabdff1aSopenharmony_ci *        All changes will have been reverted upon return.
150cabdff1aSopenharmony_ci */
151cabdff1aSopenharmony_ciint ff_vorbis_stream_comment(AVFormatContext *as, AVStream *st,
152cabdff1aSopenharmony_ci                             const uint8_t *buf, int size);
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_cistatic inline int
155cabdff1aSopenharmony_ciogg_find_stream (struct ogg * ogg, int serial)
156cabdff1aSopenharmony_ci{
157cabdff1aSopenharmony_ci    int i;
158cabdff1aSopenharmony_ci
159cabdff1aSopenharmony_ci    for (i = 0; i < ogg->nstreams; i++)
160cabdff1aSopenharmony_ci        if (ogg->streams[i].serial == serial)
161cabdff1aSopenharmony_ci            return i;
162cabdff1aSopenharmony_ci
163cabdff1aSopenharmony_ci    return -1;
164cabdff1aSopenharmony_ci}
165cabdff1aSopenharmony_ci
166cabdff1aSopenharmony_cistatic inline uint64_t
167cabdff1aSopenharmony_ciogg_gptopts (AVFormatContext * s, int i, uint64_t gp, int64_t *dts)
168cabdff1aSopenharmony_ci{
169cabdff1aSopenharmony_ci    struct ogg *ogg = s->priv_data;
170cabdff1aSopenharmony_ci    struct ogg_stream *os = ogg->streams + i;
171cabdff1aSopenharmony_ci    uint64_t pts = AV_NOPTS_VALUE;
172cabdff1aSopenharmony_ci
173cabdff1aSopenharmony_ci    if(os->codec && os->codec->gptopts){
174cabdff1aSopenharmony_ci        pts = os->codec->gptopts(s, i, gp, dts);
175cabdff1aSopenharmony_ci    } else {
176cabdff1aSopenharmony_ci        pts = gp;
177cabdff1aSopenharmony_ci        if (dts)
178cabdff1aSopenharmony_ci            *dts = pts;
179cabdff1aSopenharmony_ci    }
180cabdff1aSopenharmony_ci    if (pts > INT64_MAX && pts != AV_NOPTS_VALUE) {
181cabdff1aSopenharmony_ci        // The return type is unsigned, we thus cannot return negative pts
182cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "invalid pts %"PRId64"\n", pts);
183cabdff1aSopenharmony_ci        pts = AV_NOPTS_VALUE;
184cabdff1aSopenharmony_ci    }
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci    return pts;
187cabdff1aSopenharmony_ci}
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci#endif /* AVFORMAT_OGGDEC_H */
190