3 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/crc.h"
23 #include "libavcodec/xiph.h"
24 #include "libavcodec/bytestream.h"
25 #include "libavcodec/flac.h"
31 unsigned page_counter
;
34 /** for theora granule */
41 static void ogg_update_checksum(AVFormatContext
*s
, int64_t crc_offset
)
43 int64_t pos
= url_ftell(s
->pb
);
44 uint32_t checksum
= get_checksum(s
->pb
);
45 url_fseek(s
->pb
, crc_offset
, SEEK_SET
);
46 put_be32(s
->pb
, checksum
);
47 url_fseek(s
->pb
, pos
, SEEK_SET
);
50 static int ogg_write_page(AVFormatContext
*s
, const uint8_t *data
, int size
,
51 int64_t granule
, int stream_index
, int flags
)
53 OGGStreamContext
*oggstream
= s
->streams
[stream_index
]->priv_data
;
57 if (size
>= 255*255) {
60 } else if (oggstream
->eos
)
63 page_segments
= FFMIN((size
/255)+!!size
, 255);
65 init_checksum(s
->pb
, ff_crc04C11DB7_update
, 0);
66 put_tag(s
->pb
, "OggS");
68 put_byte(s
->pb
, flags
);
69 put_le64(s
->pb
, granule
);
70 put_le32(s
->pb
, stream_index
);
71 put_le32(s
->pb
, oggstream
->page_counter
++);
72 crc_offset
= url_ftell(s
->pb
);
73 put_le32(s
->pb
, 0); // crc
74 put_byte(s
->pb
, page_segments
);
75 for (i
= 0; i
< page_segments
-1; i
++)
78 put_byte(s
->pb
, size
- (page_segments
-1)*255);
79 put_buffer(s
->pb
, data
, size
);
81 ogg_update_checksum(s
, crc_offset
);
82 put_flush_packet(s
->pb
);
86 static uint8_t *ogg_write_vorbiscomment(int offset
, int bitexact
,
89 const char *vendor
= bitexact
? "ffmpeg" : LIBAVFORMAT_IDENT
;
93 size
= offset
+ 4 + strlen(vendor
) + 4;
100 bytestream_put_le32(&p
, strlen(vendor
));
101 bytestream_put_buffer(&p
, vendor
, strlen(vendor
));
102 bytestream_put_le32(&p
, 0); // user comment list length
108 static int ogg_build_flac_headers(AVCodecContext
*avctx
,
109 OGGStreamContext
*oggstream
, int bitexact
)
111 enum FLACExtradataFormat format
;
115 if (!ff_flac_is_extradata_valid(avctx
, &format
, &streaminfo
))
118 // first packet: STREAMINFO
119 oggstream
->header_len
[0] = 51;
120 oggstream
->header
[0] = av_mallocz(51); // per ogg flac specs
121 p
= oggstream
->header
[0];
123 return AVERROR_NOMEM
;
124 bytestream_put_byte(&p
, 0x7F);
125 bytestream_put_buffer(&p
, "FLAC", 4);
126 bytestream_put_byte(&p
, 1); // major version
127 bytestream_put_byte(&p
, 0); // minor version
128 bytestream_put_be16(&p
, 1); // headers packets without this one
129 bytestream_put_buffer(&p
, "fLaC", 4);
130 bytestream_put_byte(&p
, 0x00); // streaminfo
131 bytestream_put_be24(&p
, 34);
132 bytestream_put_buffer(&p
, streaminfo
, FLAC_STREAMINFO_SIZE
);
134 // second packet: VorbisComment
135 p
= ogg_write_vorbiscomment(4, bitexact
, &oggstream
->header_len
[1]);
137 return AVERROR_NOMEM
;
138 oggstream
->header
[1] = p
;
139 bytestream_put_byte(&p
, 0x84); // last metadata block and vorbis comment
140 bytestream_put_be24(&p
, oggstream
->header_len
[1] - 4);
145 #define SPEEX_HEADER_SIZE 80
147 static int ogg_build_speex_headers(AVCodecContext
*avctx
,
148 OGGStreamContext
*oggstream
, int bitexact
)
152 if (avctx
->extradata_size
< SPEEX_HEADER_SIZE
)
155 // first packet: Speex header
156 p
= av_mallocz(SPEEX_HEADER_SIZE
);
158 return AVERROR_NOMEM
;
159 oggstream
->header
[0] = p
;
160 oggstream
->header_len
[0] = SPEEX_HEADER_SIZE
;
161 bytestream_put_buffer(&p
, avctx
->extradata
, SPEEX_HEADER_SIZE
);
162 AV_WL32(&oggstream
->header
[0][68], 0); // set extra_headers to 0
164 // second packet: VorbisComment
165 p
= ogg_write_vorbiscomment(0, bitexact
, &oggstream
->header_len
[1]);
167 return AVERROR_NOMEM
;
168 oggstream
->header
[1] = p
;
173 static int ogg_write_header(AVFormatContext
*s
)
175 OGGStreamContext
*oggstream
;
177 for (i
= 0; i
< s
->nb_streams
; i
++) {
178 AVStream
*st
= s
->streams
[i
];
179 if (st
->codec
->codec_type
== CODEC_TYPE_AUDIO
)
180 av_set_pts_info(st
, 64, 1, st
->codec
->sample_rate
);
181 else if (st
->codec
->codec_type
== CODEC_TYPE_VIDEO
)
182 av_set_pts_info(st
, 64, st
->codec
->time_base
.num
, st
->codec
->time_base
.den
);
183 if (st
->codec
->codec_id
!= CODEC_ID_VORBIS
&&
184 st
->codec
->codec_id
!= CODEC_ID_THEORA
&&
185 st
->codec
->codec_id
!= CODEC_ID_SPEEX
&&
186 st
->codec
->codec_id
!= CODEC_ID_FLAC
) {
187 av_log(s
, AV_LOG_ERROR
, "Unsupported codec id in stream %d\n", i
);
191 if (!st
->codec
->extradata
|| !st
->codec
->extradata_size
) {
192 av_log(s
, AV_LOG_ERROR
, "No extradata present\n");
195 oggstream
= av_mallocz(sizeof(*oggstream
));
196 st
->priv_data
= oggstream
;
197 if (st
->codec
->codec_id
== CODEC_ID_FLAC
) {
198 int err
= ogg_build_flac_headers(st
->codec
, oggstream
,
199 st
->codec
->flags
& CODEC_FLAG_BITEXACT
);
201 av_log(s
, AV_LOG_ERROR
, "Error writing FLAC headers\n");
202 av_freep(&st
->priv_data
);
205 } else if (st
->codec
->codec_id
== CODEC_ID_SPEEX
) {
206 int err
= ogg_build_speex_headers(st
->codec
, oggstream
,
207 st
->codec
->flags
& CODEC_FLAG_BITEXACT
);
209 av_log(s
, AV_LOG_ERROR
, "Error writing Speex headers\n");
210 av_freep(&st
->priv_data
);
214 if (ff_split_xiph_headers(st
->codec
->extradata
, st
->codec
->extradata_size
,
215 st
->codec
->codec_id
== CODEC_ID_VORBIS
? 30 : 42,
216 oggstream
->header
, oggstream
->header_len
) < 0) {
217 av_log(s
, AV_LOG_ERROR
, "Extradata corrupted\n");
218 av_freep(&st
->priv_data
);
221 if (st
->codec
->codec_id
== CODEC_ID_THEORA
) {
222 /** KFGSHIFT is the width of the less significant section of the granule position
223 The less significant section is the frame count since the last keyframe */
224 oggstream
->kfgshift
= ((oggstream
->header
[0][40]&3)<<3)|(oggstream
->header
[0][41]>>5);
225 oggstream
->vrev
= oggstream
->header
[0][9];
226 av_log(s
, AV_LOG_DEBUG
, "theora kfgshift %d, vrev %d\n",
227 oggstream
->kfgshift
, oggstream
->vrev
);
231 for (i
= 0; i
< 3; i
++) {
232 for (j
= 0; j
< s
->nb_streams
; j
++) {
233 AVStream
*st
= s
->streams
[j
];
234 OGGStreamContext
*oggstream
= st
->priv_data
;
235 if (oggstream
&& oggstream
->header_len
[i
]) {
236 ogg_write_page(s
, oggstream
->header
[i
], oggstream
->header_len
[i
],
237 0, st
->index
, i
? 0 : 2); // bos
244 static int ogg_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
246 AVStream
*st
= s
->streams
[pkt
->stream_index
];
247 OGGStreamContext
*oggstream
= st
->priv_data
;
248 uint8_t *ptr
= pkt
->data
;
249 int ret
, size
= pkt
->size
;
252 if (st
->codec
->codec_id
== CODEC_ID_THEORA
) {
253 int64_t pts
= oggstream
->vrev
< 1 ? pkt
->pts
: pkt
->pts
+ pkt
->duration
;
255 if (pkt
->flags
& PKT_FLAG_KEY
)
256 oggstream
->last_kf_pts
= pts
;
257 pframe_count
= pts
- oggstream
->last_kf_pts
;
258 // prevent frame count from overflow if key frame flag is not set
259 if (pframe_count
>= (1<<oggstream
->kfgshift
)) {
260 oggstream
->last_kf_pts
+= pframe_count
;
263 granule
= (oggstream
->last_kf_pts
<<oggstream
->kfgshift
) | pframe_count
;
265 granule
= pkt
->pts
+ pkt
->duration
;
266 oggstream
->duration
= granule
;
268 ret
= ogg_write_page(s
, ptr
, size
, granule
, pkt
->stream_index
, ptr
!= pkt
->data
);
269 ptr
+= ret
; size
-= ret
;
270 } while (size
> 0 || ret
== 255*255); // need to output a last nil page
275 static int ogg_compare_granule(AVFormatContext
*s
, AVPacket
*next
, AVPacket
*pkt
)
277 AVStream
*st2
= s
->streams
[next
->stream_index
];
278 AVStream
*st
= s
->streams
[pkt
->stream_index
];
280 int64_t next_granule
= av_rescale_q(next
->pts
+ next
->duration
,
281 st2
->time_base
, AV_TIME_BASE_Q
);
282 int64_t cur_granule
= av_rescale_q(pkt
->pts
+ pkt
->duration
,
283 st
->time_base
, AV_TIME_BASE_Q
);
284 return next_granule
> cur_granule
;
287 static int ogg_interleave_per_granule(AVFormatContext
*s
, AVPacket
*out
, AVPacket
*pkt
, int flush
)
290 int stream_count
= 0;
291 int streams
[MAX_STREAMS
] = {0};
295 ff_interleave_add_packet(s
, pkt
, ogg_compare_granule
);
298 pktl
= s
->packet_buffer
;
300 if (streams
[pktl
->pkt
.stream_index
] == 0)
302 streams
[pktl
->pkt
.stream_index
]++;
303 // need to buffer at least one packet to set eos flag
304 if (streams
[pktl
->pkt
.stream_index
] == 2)
309 if ((s
->nb_streams
== stream_count
&& interleaved
== stream_count
) ||
310 (flush
&& stream_count
)) {
311 pktl
= s
->packet_buffer
;
313 s
->packet_buffer
= pktl
->next
;
314 if (flush
&& streams
[out
->stream_index
] == 1) {
315 OGGStreamContext
*ogg
= s
->streams
[out
->stream_index
]->priv_data
;
318 if(!s
->packet_buffer
)
319 s
->packet_buffer_end
= NULL
;
321 if(s
->streams
[out
->stream_index
]->last_in_packet_buffer
== pktl
)
322 s
->streams
[out
->stream_index
]->last_in_packet_buffer
= NULL
;
332 static int ogg_write_trailer(AVFormatContext
*s
)
335 for (i
= 0; i
< s
->nb_streams
; i
++) {
336 AVStream
*st
= s
->streams
[i
];
337 OGGStreamContext
*oggstream
= st
->priv_data
;
338 if (st
->codec
->codec_id
== CODEC_ID_FLAC
||
339 st
->codec
->codec_id
== CODEC_ID_SPEEX
) {
340 av_free(oggstream
->header
[0]);
341 av_free(oggstream
->header
[1]);
343 av_freep(&st
->priv_data
);
348 AVOutputFormat ogg_muxer
= {
350 NULL_IF_CONFIG_SMALL("Ogg"),
359 .interleave_packet
= ogg_interleave_per_granule
,