1 /*
2 * Ogg muxer
3 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr>
4 *
5 * This file is part of FFmpeg.
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include <stdint.h>
23
35
36 #define MAX_PAGE_SIZE 65025
37
48
53 /** for theora granule */
63
68
72 int pref_size;
///< preferred page size (0 => fill all segments)
73 int64_t
pref_duration;
///< preferred page duration (0 => fill all segments)
76
77 #define OFFSET(x) offsetof(OGGContext, x)
78 #define PARAM AV_OPT_FLAG_ENCODING_PARAM
79
81 { "serial_offset", "serial number offset",
83 { "oggpagesize", "Set preferred Ogg page size.",
85 { "pagesize", "preferred page size in bytes (deprecated)",
87 { "page_duration", "preferred page duration, in microseconds",
90 };
91
92 #define OGG_CLASS(flavor, name)\
93 static const AVClass flavor ## _muxer_class = {\
94 .class_name = #name " muxer",\
95 .item_name = av_default_item_name,\
96 .option = options,\
97 .version = LIBAVUTIL_VERSION_INT,\
98 };
99
101 {
107 }
108
110 {
113 int64_t crc_offset;
116
118 if (ret < 0)
132
135
137 if (size < 0)
139
144 return 0;
145 }
146
148 {
150 }
151
153 {
155 return (granule>>oggstream->
kfgshift) +
156 (granule & ((1<<oggstream->
kfgshift)-1));
157 else
158 return granule;
159 }
160
162 {
165 int64_t next_granule, cur_granule;
166
168 return 0;
169
174 return next_granule > cur_granule;
175 }
176
178 {
183 return 0;
184 }
185
187 {
191
192 if (!l)
195
199
200 while (*p) {
202 break;
204 }
206 *p = l;
207
208 return 0;
209 }
210
214 {
217 int total_segments = size / 255 + 1;
220
221 // Handles VFR by flushing page because this frame needs to have a timestamp
222 // For theora, keyframes also need to have a timestamp to correctly mark
223 // them as such, otherwise seeking will not work correctly at the very
224 // least with old libogg versions.
225 // Do not try to flush header packets though, that will create broken files.
232 flush = 1;
233 }
234
235 // avoid a continued page
236 if (!header && oggstream->
page.
size > 0 &&
239 }
240
241 for (i = 0; i < total_segments; ) {
243
245
247 page->
flags |= 1;
// continued packet
248
251
252 len =
FFMIN(size, segments*255);
254 memcpy(page->
data+page->
size, p, len);
257 i += segments;
259
260 if (i == total_segments)
262
263 if (!header) {
265
270
275 }
276 }
277 }
278
281
282 return 0;
283 }
284
287 {
291
293
296 if (!p)
298 p0 = p;
299
302 if (framing_bit)
303 bytestream_put_byte(&p, 1);
304
306 return p0;
307 }
308
312 {
314
317
318 // first packet: STREAMINFO
322 if (!p)
324 bytestream_put_byte(&p, 0x7F);
326 bytestream_put_byte(&p, 1); // major version
327 bytestream_put_byte(&p, 0); // minor version
328 bytestream_put_be16(&p, 1); // headers packets without this one
330 bytestream_put_byte(&p, 0x00); // streaminfo
331 bytestream_put_be24(&p, 34);
333
334 // second packet: VorbisComment
336 if (!p)
339 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment
340 bytestream_put_be24(&p, oggstream->
header_len[1] - 4);
341
342 return 0;
343 }
344
345 #define SPEEX_HEADER_SIZE 80
346
350 {
352
355
356 // first packet: Speex header
358 if (!p)
363 AV_WL32(&oggstream->
header[0][68], 0);
// set extra_headers to 0
364
365 // second packet: VorbisComment
367 if (!p)
370
371 return 0;
372 }
373
374 #define OPUS_HEADER_SIZE 19
375
379 {
381
384
385 /* first packet: Opus header */
387 if (!p)
392
393 /* second packet: VorbisComment */
395 if (!p)
399
400 return 0;
401 }
402
404 {
407
409 return;
410
415 break;
417 flush == 1 && oggstream->
page_count == 1 ? 4 : 0);
// eos
420 p = next;
421 }
423 }
424
426 {
429 int i, j;
430
433
437
440 /* Opus requires a fixed 48kHz clock */
442 else
444 }
445
453 }
454
458 }
460 if (!oggstream)
462
464
466 do {
468 for (j = 0; j < i; j++) {
471 break;
472 }
473 } while (j < i);
475
477
483 if (err) {
486 return err;
487 }
492 if (err) {
495 return err;
496 }
501 if (err) {
504 return err;
505 }
506 } else {
511
518 }
519
522 framing_bit);
524 if (!p)
526
527 bytestream_put_byte(&p, header_type);
529
531 /** KFGSHIFT is the width of the less significant section of the granule position
532 The less significant section is the frame count since the last keyframe */
537 }
538 }
539 }
540
547 }
551 for (i = 1; i < 3; i++) {
555 }
557 }
558
560
562
563 return 0;
564 }
565
567 {
571 int64_t granule;
572
575 int pframe_count;
579 // prevent frame count from overflow if key frame flag is not set
580 if (pframe_count >= (1<<oggstream->
kfgshift)) {
582 pframe_count = 0;
583 }
589 st->time_base);
590 else
592
594 oggstream->page.start_granule =
pkt->
pts;
595
599
601
602 oggstream->last_granule = granule;
603
604 return 0;
605 }
606
608 {
609 int i;
610
611 if (pkt)
613
618 }
619
621 return 0;
622 }
623
625 {
626 int i;
627
628 /* flush current page if needed */
631
634 }
635
637
645 }
648 }
649 return 0;
650 }
651
652 #if CONFIG_OGG_MUXER
657 .mime_type = "application/ogg",
658 .extensions = "ogg,ogv"
659 #if !CONFIG_SPX_MUXER
660 ",spx"
661 #endif
662 #if !CONFIG_OPUS_MUXER
663 ",opus"
664 #endif
665 ,
667 .audio_codec = CONFIG_LIBVORBIS_ENCODER ?
674 .priv_class = &ogg_muxer_class,
675 };
676 #endif
677
678 #if CONFIG_OGA_MUXER
683 .mime_type = "audio/ogg",
684 .extensions = "oga",
686 .audio_codec = CONFIG_LIBVORBIS_ENCODER ?
692 .priv_class = &oga_muxer_class,
693 };
694 #endif
695
696 #if CONFIG_SPX_MUXER
701 .mime_type = "audio/ogg",
702 .extensions = "spx",
709 .priv_class = &spx_muxer_class,
710 };
711 #endif
712
713 #if CONFIG_OPUS_MUXER
718 .mime_type = "audio/ogg",
719 .extensions = "opus",
726 .priv_class = &opus_muxer_class,
727 };
728 #endif