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 "config_components.h"
23
24 #include <stdint.h>
25
39
40 #define MAX_PAGE_SIZE 65025
41
52
57 /** for theora granule */
61 /* for VP8 granule */
69
74
78 int pref_size;
///< preferred page size (0 => fill all segments)
82
83 #define OFFSET(x) offsetof(OGGContext, x)
84 #define PARAM AV_OPT_FLAG_ENCODING_PARAM
85
87 { "serial_offset", "serial number offset",
89 { "oggpagesize", "Set preferred Ogg page size.",
91 { "pagesize", "preferred page size in bytes (deprecated)",
93 { "page_duration", "preferred page duration, in microseconds",
96 };
97
99 .
class_name =
"Ogg (audio/video/Speex/Opus) muxer",
103 };
104
106 {
108 uint8_t buf[4 + 1 + 1 + 8 + 4 + 4 + 4 + 1 + 255], *ptr = buf, *crc_pos;
110 uint32_t crc;
111
112 bytestream_put_le32(&ptr,
MKTAG(
'O',
'g',
'g',
'S'));
113 bytestream_put_byte(&ptr, 0);
114 bytestream_put_byte(&ptr, page->
flags | extra_flags);
115 bytestream_put_le64(&ptr, page->
granule);
116 bytestream_put_le32(&ptr, oggstream->
serial_num);
118 crc_pos = ptr;
119 bytestream_put_le32(&ptr, 0);
122
123 crc =
av_crc(crc_table, 0, buf, ptr - buf);
125 bytestream_put_be32(&crc_pos, crc);
126
131 }
132
134 {
135 return (oggstream->
kfgshift && !(granule & ((1<<oggstream->
kfgshift)-1))) ||
136 (oggstream->
isvp8 && !((granule >> 3) & 0x07ffffff));
137 }
138
140 {
142 return (granule>>oggstream->
kfgshift) +
143 (granule & ((1<<oggstream->
kfgshift)-1));
144 else if (oggstream->
isvp8)
145 return granule >> 32;
146 else
147 return granule;
148 }
149
151 {
154 int64_t next_granule, cur_granule;
155
157 return 0;
158
163 return next_granule > cur_granule;
164 }
165
167 {
172 return 0;
173 }
174
176 {
180
181 if (!l)
184
188
189 while (*p) {
191 break;
193 }
195 *p = l;
196
197 return 0;
198 }
199
203 {
206 int total_segments =
size / 255 + 1;
207 const uint8_t *p =
data;
209
210 // Handles VFR by flushing page because this frame needs to have a timestamp
211 // For theora and VP8, keyframes also need to have a timestamp to correctly mark
212 // them as such, otherwise seeking will not work correctly at the very
213 // least with old libogg versions.
214 // Do not try to flush header packets though, that will create broken files.
222 }
223
224 // avoid a continued page
228 }
229
230 for (
i = 0;
i < total_segments; ) {
232
234
236 page->
flags |= 1;
// continued packet
237
240
248
249 if (
i == total_segments)
251
252 {
254
259
263 if ((
ogg->pref_size > 0 && page->
size >=
ogg->pref_size) ||
264 (
ogg->pref_duration > 0 && next - start >=
ogg->pref_duration)) {
266 }
267 }
268 }
269 }
270
273
274 return 0;
275 }
276
279 AVChapter **chapters,
unsigned int nb_chapters)
280 {
284 uint8_t *p;
285
287
292 if (!p)
294
297 if (framing_bit)
299
301 return p;
302 }
303
307 {
308 uint8_t *p;
309
312
313 // first packet: STREAMINFO
317 if (!p)
319 bytestream_put_byte(&p, 0x7F);
321 bytestream_put_byte(&p, 1); // major version
322 bytestream_put_byte(&p, 0); // minor version
323 bytestream_put_be16(&p, 1); // headers packets without this one
325 bytestream_put_byte(&p, 0x00); // streaminfo
326 bytestream_put_be24(&p, 34);
328
329 // second packet: VorbisComment
331 if (!p)
334 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment
335 bytestream_put_be24(&p, oggstream->
header_len[1] - 4);
336
337 return 0;
338 }
339
340 #define SPEEX_HEADER_SIZE 80
341
345 {
346 uint8_t *p;
347
350
351 // first packet: Speex header
353 if (!p)
358 AV_WL32(&oggstream->
header[0][68], 0);
// set extra_headers to 0
359
360 // second packet: VorbisComment
362 if (!p)
365
366 return 0;
367 }
368
369 #define OPUS_HEADER_SIZE 19
370
374 unsigned int nb_chapters)
375 {
376 uint8_t *p;
377
380
381 /* first packet: Opus header */
383 if (!p)
388
389 /* second packet: VorbisComment */
391 if (!p)
395
396 return 0;
397 }
398
399 #define VP8_HEADER_SIZE 26
400
403 {
405 uint8_t *p;
406
407 /* first packet: VP8 header */
409 if (!p)
413 bytestream_put_byte(&p, 0x4f); // HDRID
415 bytestream_put_byte(&p, 1); // HDRTYP
416 bytestream_put_byte(&p, 1); // VMAJ
417 bytestream_put_byte(&p, 0); // VMIN
418 bytestream_put_be16(&p, par->
width);
419 bytestream_put_be16(&p, par->
height);
423 // OggVP8 requires pts to increase by 1 per visible frame, so use the least common
424 // multiple framerate if available.
429 }
432
433 /* optional second packet: VorbisComment */
436 if (!p)
439 bytestream_put_byte(&p, 0x4f); // HDRID
441 bytestream_put_byte(&p, 2); // HDRTYP
442 bytestream_put_byte(&p, 0x20);
443 }
444
445 oggstream->
isvp8 = 1;
446
447 return 0;
448 }
449
451 {
454
456 return;
457
458 for (p =
ogg->page_list; p; ) {
462 break;
467 p = next;
468 }
470 }
471
473 {
477
480
481 for (
i = 0;
i <
s->nb_streams;
i++) {
483 unsigned serial_num =
i +
ogg->serial_offset;
484
487 /* Opus requires a fixed 48kHz clock */
489 else
491 }
492
501 }
502
507 }
509 if (!oggstream)
511
513
515 do {
517 for (j = 0; j <
i; j++) {
520 break;
521 }
524
526
532 if (err) {
534 return err;
535 }
540 if (err) {
542 return err;
543 }
548 if (err) {
550 return err;
551 }
555 if (err) {
557 return err;
558 }
559 } else {
560 uint8_t *p;
564
571 }
572
575 framing_bit,
NULL, 0);
577 if (!p)
579
580 bytestream_put_byte(&p, header_type);
582
585 /* Make sure to use time base stored in the Theora stream header to write
586 correct timestamps */
591 }
592 /** KFGSHIFT is the width of the less significant section of the granule position
593 The less significant section is the frame count since the last keyframe */
598 }
599 }
600 }
601
602 return 0;
603 }
604
606 {
609
610 for (j = 0; j <
s->nb_streams; j++) {
611 oggstream =
s->streams[j]->priv_data;
616 }
617 for (j = 0; j <
s->nb_streams; j++) {
620 for (
i = 1;
i < 3;
i++) {
624 }
626 }
627
629
631
632 return 0;
633 }
634
636 {
641
644 int pframe_count;
648 // prevent frame count from overflow if key frame flag is not set
649 if (pframe_count >= (1<<oggstream->
kfgshift)) {
651 pframe_count = 0;
652 }
661 int visible;
662
663 visible = (
pkt->
data[0] >> 4) & 1;
666 invcnt = visible ? 3 : (invcnt == 3 ? 0 : invcnt + 1);
668
669 granule = (
pts << 32) | (invcnt << 30) | (dist << 3);
670 } else
672
675
679
681
683
684 return 0;
685 }
686
688 {
690
693
694 for (
i = 0;
i <
s->nb_streams;
i++) {
698 }
699
701 return 1;
702 }
703
705 {
707
708 /* flush current page if needed */
709 for (
i = 0;
i <
s->nb_streams;
i++) {
711
714 }
715
717
718 return 0;
719 }
720
722 {
726
727 for (
i = 0;
i <
s->nb_streams;
i++) {
730 if (!oggstream)
731 continue;
737 }
739 }
740
741 while (p) {
744 p = next;
745 }
747 }
748
749 #if CONFIG_OGG_MUXER
753 .p.mime_type = "application/ogg",
754 .p.extensions = "ogg"
755 #if !CONFIG_OGV_MUXER
756 ",ogv"
757 #endif
758 #if !CONFIG_SPX_MUXER
759 ",spx"
760 #endif
761 #if !CONFIG_OPUS_MUXER
762 ",opus"
763 #endif
764 ,
766 .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ?
778 #endif
781 };
782 #endif
783
784 #if CONFIG_OGA_MUXER
788 .p.mime_type = "audio/ogg",
789 .p.extensions = "oga",
801 #endif
804 };
805 #endif
806
807 #if CONFIG_OGV_MUXER
811 .p.mime_type = "video/ogg",
812 .p.extensions = "ogv",
814 .p.audio_codec = CONFIG_LIBVORBIS_ENCODER ?
816 .p.video_codec = CONFIG_LIBTHEORA_ENCODER ?
827 #endif
830 };
831 #endif
832
833 #if CONFIG_SPX_MUXER
837 .p.mime_type = "audio/ogg",
838 .p.extensions = "spx",
850 #endif
853 };
854 #endif
855
856 #if CONFIG_OPUS_MUXER
860 .p.mime_type = "audio/ogg",
861 .p.extensions = "opus",
873 #endif
876 };
877 #endif