2 * Copyright (c) 2013-2014 Mozilla Corporation
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Determines the duration for each packet.
29 #include "bytestream.h"
33 typedef struct OpusParseContext
{
41 static const uint8_t *parse_opus_ts_header(const uint8_t *start
, int *payload_len
, int buf_len
)
43 const uint8_t *buf
= start
+ 1;
44 int start_trim_flag
, end_trim_flag
, control_extension_flag
, control_extension_length
;
48 bytestream2_init(&gb
, buf
, buf_len
);
50 flags
= bytestream2_get_byte(&gb
);
51 start_trim_flag
= (flags
>> 4) & 1;
52 end_trim_flag
= (flags
>> 3) & 1;
53 control_extension_flag
= (flags
>> 2) & 1;
56 while (bytestream2_peek_byte(&gb
) == 0xff)
57 *payload_len
+= bytestream2_get_byte(&gb
);
59 *payload_len
+= bytestream2_get_byte(&gb
);
62 bytestream2_skip(&gb
, 2);
64 bytestream2_skip(&gb
, 2);
65 if (control_extension_flag
) {
66 control_extension_length
= bytestream2_get_byte(&gb
);
67 bytestream2_skip(&gb
, control_extension_length
);
70 return buf
+ bytestream2_tell(&gb
);
74 * Find the end of the current frame in the bitstream.
75 * @return the position of the first byte of the next frame, or -1
77 static int opus_find_frame_end(AVCodecParserContext
*ctx
, AVCodecContext
*avctx
,
78 const uint8_t *buf
, int buf_size
, int *header_len
)
80 OpusParseContext
*s
= ctx
->priv_data
;
81 ParseContext
*pc
= &s
->pc
;
82 int ret
, start_found
, i
= 0, payload_len
= 0;
83 const uint8_t *payload
;
91 start_found
= pc
->frame_start_found
;
95 /* Check if we're using Opus in MPEG-TS framing */
96 if (!s
->ts_framing
&& buf_size
> 2) {
98 if ((hdr
& OPUS_TS_MASK
) == OPUS_TS_HEADER
)
102 if (s
->ts_framing
&& !start_found
) {
103 for (i
= 0; i
< buf_size
-2; i
++) {
104 state
= (state
<< 8) | payload
[i
];
105 if ((state
& OPUS_TS_MASK
) == OPUS_TS_HEADER
) {
106 payload
= parse_opus_ts_header(payload
, &payload_len
, buf_size
- i
);
107 *header_len
= payload
- buf
;
115 payload_len
= buf_size
;
117 if (avctx
->extradata
&& !s
->extradata_parsed
) {
118 ret
= ff_opus_parse_extradata(avctx
, &s
->ctx
);
120 av_log(avctx
, AV_LOG_ERROR
, "Error parsing Ogg extradata.\n");
121 return AVERROR_INVALIDDATA
;
123 av_freep(&s
->ctx
.channel_maps
);
124 s
->extradata_parsed
= 1;
127 if (payload_len
<= buf_size
&& (!s
->ts_framing
|| start_found
)) {
128 ret
= ff_opus_parse_packet(&s
->pkt
, payload
, payload_len
, s
->ctx
.nb_streams
> 1);
130 av_log(avctx
, AV_LOG_ERROR
, "Error parsing Opus packet header.\n");
131 pc
->frame_start_found
= 0;
132 return AVERROR_INVALIDDATA
;
135 ctx
->duration
= s
->pkt
.frame_count
* s
->pkt
.frame_duration
;
140 if (payload_len
+ *header_len
<= buf_size
) {
141 pc
->frame_start_found
= 0;
143 return payload_len
+ *header_len
;
147 pc
->frame_start_found
= start_found
;
149 return END_NOT_FOUND
;
155 static int opus_parse(AVCodecParserContext
*ctx
, AVCodecContext
*avctx
,
156 const uint8_t **poutbuf
, int *poutbuf_size
,
157 const uint8_t *buf
, int buf_size
)
159 OpusParseContext
*s
= ctx
->priv_data
;
160 ParseContext
*pc
= &s
->pc
;
161 int next
, header_len
;
163 next
= opus_find_frame_end(ctx
, avctx
, buf
, buf_size
, &header_len
);
165 if (s
->ts_framing
&& next
!= AVERROR_INVALIDDATA
&&
166 ff_combine_frame(pc
, next
, &buf
, &buf_size
) < 0) {
172 if (next
== AVERROR_INVALIDDATA
){
178 *poutbuf
= buf
+ header_len
;
179 *poutbuf_size
= buf_size
- header_len
;
183 AVCodecParser ff_opus_parser
= {
184 .codec_ids
= { AV_CODEC_ID_OPUS
},
185 .priv_data_size
= sizeof(OpusParseContext
),
186 .parser_parse
= opus_parse
,
187 .parser_close
= ff_parse_close