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 "config_components.h"
26 #include "libavutil/crc.h"
27 #include "libavutil/mathematics.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/opt.h"
30 #include "libavutil/random_seed.h"
31 #include "libavcodec/xiph.h"
32 #include "libavcodec/bytestream.h"
33 #include "libavcodec/flac.h"
35 #include "avio_internal.h"
39 #include "vorbiscomment.h"
41 #define MAX_PAGE_SIZE 65025
43 typedef struct OGGPage
{
44 int64_t start_granule
;
48 uint8_t segments_count
;
49 uint8_t segments
[255];
50 uint8_t data
[MAX_PAGE_SIZE
];
54 typedef struct OGGStreamContext
{
55 unsigned page_counter
;
58 /** for theora granule */
65 unsigned page_count
; ///< number of page buffered
66 OGGPage page
; ///< current page
67 unsigned serial_num
; ///< serial number
68 int64_t last_granule
; ///< last packet granule
71 typedef struct OGGPageList
{
73 struct OGGPageList
*next
;
76 typedef struct OGGContext
{
78 OGGPageList
*page_list
;
79 #if LIBAVFORMAT_VERSION_MAJOR < 63
80 int pref_size
; ///< preferred page size (0 => fill all segments)
82 int64_t pref_duration
; ///< preferred page duration (0 => fill all segments)
86 #define OFFSET(x) offsetof(OGGContext, x)
87 #define PARAM AV_OPT_FLAG_ENCODING_PARAM
89 static const AVOption options
[] = {
90 { "serial_offset", "serial number offset",
91 OFFSET(serial_offset
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, INT_MAX
, PARAM
},
92 #if LIBAVFORMAT_VERSION_MAJOR < 63
93 { "oggpagesize", "Set preferred Ogg page size.",
94 OFFSET(pref_size
), AV_OPT_TYPE_INT
, {.i64
= 0}, 0, MAX_PAGE_SIZE
, PARAM
| AV_OPT_FLAG_DEPRECATED
},
95 { "pagesize", "preferred page size in bytes",
96 OFFSET(pref_size
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, MAX_PAGE_SIZE
, PARAM
| AV_OPT_FLAG_DEPRECATED
},
98 { "page_duration", "preferred page duration, in microseconds",
99 OFFSET(pref_duration
), AV_OPT_TYPE_INT64
, { .i64
= 1000000 }, 0, INT64_MAX
, PARAM
},
103 static const AVClass ogg_muxer_class
= {
104 .class_name
= "Ogg (audio/video/Speex/Opus) muxer",
105 .item_name
= av_default_item_name
,
107 .version
= LIBAVUTIL_VERSION_INT
,
110 static void ogg_write_page(AVFormatContext
*s
, OGGPage
*page
, int extra_flags
)
112 OGGStreamContext
*oggstream
= s
->streams
[page
->stream_index
]->priv_data
;
113 uint8_t buf
[4 + 1 + 1 + 8 + 4 + 4 + 4 + 1 + 255], *ptr
= buf
, *crc_pos
;
114 const AVCRC
*crc_table
= av_crc_get_table(AV_CRC_32_IEEE
);
117 bytestream_put_le32(&ptr
, MKTAG('O', 'g', 'g', 'S'));
118 bytestream_put_byte(&ptr
, 0);
119 bytestream_put_byte(&ptr
, page
->flags
| extra_flags
);
120 bytestream_put_le64(&ptr
, page
->granule
);
121 bytestream_put_le32(&ptr
, oggstream
->serial_num
);
122 bytestream_put_le32(&ptr
, oggstream
->page_counter
++);
124 bytestream_put_le32(&ptr
, 0);
125 bytestream_put_byte(&ptr
, page
->segments_count
);
126 bytestream_put_buffer(&ptr
, page
->segments
, page
->segments_count
);
128 crc
= av_crc(crc_table
, 0, buf
, ptr
- buf
);
129 crc
= av_crc(crc_table
, crc
, page
->data
, page
->size
);
130 bytestream_put_be32(&crc_pos
, crc
);
132 avio_write(s
->pb
, buf
, ptr
- buf
);
133 avio_write(s
->pb
, page
->data
, page
->size
);
134 avio_write_marker(s
->pb
, AV_NOPTS_VALUE
, AVIO_DATA_MARKER_FLUSH_POINT
);
135 oggstream
->page_count
--;
138 static int ogg_key_granule(OGGStreamContext
*oggstream
, int64_t granule
)
140 return (oggstream
->kfgshift
&& !(granule
& ((1<<oggstream
->kfgshift
)-1))) ||
141 (oggstream
->isvp8
&& !((granule
>> 3) & 0x07ffffff));
144 static int64_t ogg_granule_to_timestamp(OGGStreamContext
*oggstream
, int64_t granule
)
146 if (oggstream
->kfgshift
)
147 return (granule
>>oggstream
->kfgshift
) +
148 (granule
& ((1<<oggstream
->kfgshift
)-1));
149 else if (oggstream
->isvp8
)
150 return granule
>> 32;
155 static int ogg_compare_granule(AVFormatContext
*s
, OGGPage
*next
, OGGPage
*page
)
157 AVStream
*st2
= s
->streams
[next
->stream_index
];
158 AVStream
*st
= s
->streams
[page
->stream_index
];
159 int64_t next_granule
, cur_granule
;
161 if (next
->granule
== -1 || page
->granule
== -1)
164 next_granule
= av_rescale_q(ogg_granule_to_timestamp(st2
->priv_data
, next
->granule
),
165 st2
->time_base
, AV_TIME_BASE_Q
);
166 cur_granule
= av_rescale_q(ogg_granule_to_timestamp(st
->priv_data
, page
->granule
),
167 st
->time_base
, AV_TIME_BASE_Q
);
168 return next_granule
> cur_granule
;
171 static int ogg_reset_cur_page(OGGStreamContext
*oggstream
)
173 oggstream
->page
.granule
= -1;
174 oggstream
->page
.flags
= 0;
175 oggstream
->page
.segments_count
= 0;
176 oggstream
->page
.size
= 0;
180 static int ogg_buffer_page(AVFormatContext
*s
, OGGStreamContext
*oggstream
)
182 OGGContext
*ogg
= s
->priv_data
;
183 OGGPageList
**p
= &ogg
->page_list
;
184 OGGPageList
*l
= av_mallocz(sizeof(*l
));
187 return AVERROR(ENOMEM
);
188 l
->page
= oggstream
->page
;
190 oggstream
->page
.start_granule
= ogg_granule_to_timestamp(oggstream
, oggstream
->page
.granule
);
191 oggstream
->page_count
++;
192 ogg_reset_cur_page(oggstream
);
195 if (ogg_compare_granule(s
, &(*p
)->page
, &l
->page
))
205 static int ogg_buffer_data(AVFormatContext
*s
, AVStream
*st
,
206 const uint8_t *data
, unsigned size
, int64_t granule
,
209 OGGStreamContext
*oggstream
= st
->priv_data
;
210 OGGContext
*ogg
= s
->priv_data
;
211 int total_segments
= size
/ 255 + 1;
212 const uint8_t *p
= data
;
213 int i
, segments
, len
, flush
= 0;
215 // Handles VFR by flushing page because this frame needs to have a timestamp
216 // For theora and VP8, keyframes also need to have a timestamp to correctly mark
217 // them as such, otherwise seeking will not work correctly at the very
218 // least with old libogg versions.
219 // Do not try to flush header packets though, that will create broken files.
220 if ((st
->codecpar
->codec_id
== AV_CODEC_ID_THEORA
|| st
->codecpar
->codec_id
== AV_CODEC_ID_VP8
) && !header
&&
221 (ogg_granule_to_timestamp(oggstream
, granule
) >
222 ogg_granule_to_timestamp(oggstream
, oggstream
->last_granule
) + 1 ||
223 ogg_key_granule(oggstream
, granule
))) {
224 if (oggstream
->page
.granule
!= -1)
225 ogg_buffer_page(s
, oggstream
);
229 // avoid a continued page
230 if (!header
&& oggstream
->page
.size
> 0 &&
231 MAX_PAGE_SIZE
- oggstream
->page
.size
< size
) {
232 ogg_buffer_page(s
, oggstream
);
235 for (i
= 0; i
< total_segments
; ) {
236 OGGPage
*page
= &oggstream
->page
;
238 segments
= FFMIN(total_segments
- i
, 255 - page
->segments_count
);
240 if (i
&& !page
->segments_count
)
241 page
->flags
|= 1; // continued packet
243 memset(page
->segments
+page
->segments_count
, 255, segments
- 1);
244 page
->segments_count
+= segments
- 1;
246 len
= FFMIN(size
, segments
*255);
247 page
->segments
[page
->segments_count
++] = len
- (segments
-1)*255;
249 memcpy(page
->data
+page
->size
, p
, len
);
255 if (i
== total_segments
)
256 page
->granule
= granule
;
259 AVStream
*st
= s
->streams
[page
->stream_index
];
261 int64_t start
= av_rescale_q(page
->start_granule
, st
->time_base
,
263 int64_t next
= av_rescale_q(ogg_granule_to_timestamp(oggstream
, page
->granule
),
264 st
->time_base
, AV_TIME_BASE_Q
);
266 if (page
->segments_count
== 255) {
267 ogg_buffer_page(s
, oggstream
);
268 } else if (!header
) {
269 #if LIBAVFORMAT_VERSION_MAJOR < 63
270 if ((ogg
->pref_size
> 0 && page
->size
>= ogg
->pref_size
) ||
271 (ogg
->pref_duration
> 0 && next
- start
>= ogg
->pref_duration
)) {
273 if (ogg
->pref_duration
> 0 && next
- start
>= ogg
->pref_duration
) {
275 ogg_buffer_page(s
, oggstream
);
281 if (flush
&& oggstream
->page
.granule
!= -1)
282 ogg_buffer_page(s
, oggstream
);
287 static uint8_t *ogg_write_vorbiscomment(int64_t offset
, int bitexact
,
288 int *header_len
, AVDictionary
**m
, int framing_bit
,
289 AVChapter
**chapters
, unsigned int nb_chapters
)
291 const char *vendor
= bitexact
? "ffmpeg" : LIBAVFORMAT_IDENT
;
296 ff_metadata_conv(m
, ff_vorbiscomment_metadata_conv
, NULL
);
298 size
= offset
+ ff_vorbiscomment_length(*m
, vendor
, chapters
, nb_chapters
) + framing_bit
;
301 p
= av_mallocz(size
);
305 ffio_init_write_context(&pb
, p
+ offset
, size
- offset
);
306 ff_vorbiscomment_write(&pb
.pub
, *m
, vendor
, chapters
, nb_chapters
);
314 static int ogg_build_flac_headers(AVCodecParameters
*par
,
315 OGGStreamContext
*oggstream
, int bitexact
,
320 if (par
->extradata_size
< FLAC_STREAMINFO_SIZE
)
321 return AVERROR(EINVAL
);
323 // first packet: STREAMINFO
324 oggstream
->header_len
[0] = 51;
325 oggstream
->header
[0] = av_mallocz(51); // per ogg flac specs
326 p
= oggstream
->header
[0];
328 return AVERROR(ENOMEM
);
329 bytestream_put_byte(&p
, 0x7F);
330 bytestream_put_buffer(&p
, "FLAC", 4);
331 bytestream_put_byte(&p
, 1); // major version
332 bytestream_put_byte(&p
, 0); // minor version
333 bytestream_put_be16(&p
, 1); // headers packets without this one
334 bytestream_put_buffer(&p
, "fLaC", 4);
335 bytestream_put_byte(&p
, 0x00); // streaminfo
336 bytestream_put_be24(&p
, 34);
337 bytestream_put_buffer(&p
, par
->extradata
, FLAC_STREAMINFO_SIZE
);
339 // second packet: VorbisComment
340 p
= ogg_write_vorbiscomment(4, bitexact
, &oggstream
->header_len
[1], m
, 0, NULL
, 0);
342 return AVERROR(ENOMEM
);
343 oggstream
->header
[1] = p
;
344 bytestream_put_byte(&p
, 0x84); // last metadata block and vorbis comment
345 bytestream_put_be24(&p
, oggstream
->header_len
[1] - 4);
350 #define SPEEX_HEADER_SIZE 80
352 static int ogg_build_speex_headers(AVCodecParameters
*par
,
353 OGGStreamContext
*oggstream
, int bitexact
,
358 if (par
->extradata_size
< SPEEX_HEADER_SIZE
)
359 return AVERROR_INVALIDDATA
;
361 // first packet: Speex header
362 p
= av_mallocz(SPEEX_HEADER_SIZE
);
364 return AVERROR(ENOMEM
);
365 oggstream
->header
[0] = p
;
366 oggstream
->header_len
[0] = SPEEX_HEADER_SIZE
;
367 bytestream_put_buffer(&p
, par
->extradata
, SPEEX_HEADER_SIZE
);
368 AV_WL32(&oggstream
->header
[0][68], 0); // set extra_headers to 0
370 // second packet: VorbisComment
371 p
= ogg_write_vorbiscomment(0, bitexact
, &oggstream
->header_len
[1], m
, 0, NULL
, 0);
373 return AVERROR(ENOMEM
);
374 oggstream
->header
[1] = p
;
379 #define OPUS_HEADER_SIZE 19
381 static int ogg_build_opus_headers(AVCodecParameters
*par
,
382 OGGStreamContext
*oggstream
, int bitexact
,
383 AVDictionary
**m
, AVChapter
**chapters
,
384 unsigned int nb_chapters
)
388 if (par
->extradata_size
< OPUS_HEADER_SIZE
)
389 return AVERROR_INVALIDDATA
;
391 /* first packet: Opus header */
392 p
= av_mallocz(par
->extradata_size
);
394 return AVERROR(ENOMEM
);
395 oggstream
->header
[0] = p
;
396 oggstream
->header_len
[0] = par
->extradata_size
;
397 bytestream_put_buffer(&p
, par
->extradata
, par
->extradata_size
);
399 /* second packet: VorbisComment */
400 p
= ogg_write_vorbiscomment(8, bitexact
, &oggstream
->header_len
[1], m
, 0, chapters
, nb_chapters
);
402 return AVERROR(ENOMEM
);
403 oggstream
->header
[1] = p
;
404 bytestream_put_buffer(&p
, "OpusTags", 8);
409 #define VP8_HEADER_SIZE 26
411 static int ogg_build_vp8_headers(AVFormatContext
*s
, AVStream
*st
,
412 OGGStreamContext
*oggstream
, int bitexact
)
414 AVCodecParameters
*par
= st
->codecpar
;
417 /* first packet: VP8 header */
418 p
= av_mallocz(VP8_HEADER_SIZE
);
420 return AVERROR(ENOMEM
);
421 oggstream
->header
[0] = p
;
422 oggstream
->header_len
[0] = VP8_HEADER_SIZE
;
423 bytestream_put_byte(&p
, 0x4f); // HDRID
424 bytestream_put_buffer(&p
, "VP80", 4); // Identifier
425 bytestream_put_byte(&p
, 1); // HDRTYP
426 bytestream_put_byte(&p
, 1); // VMAJ
427 bytestream_put_byte(&p
, 0); // VMIN
428 bytestream_put_be16(&p
, par
->width
);
429 bytestream_put_be16(&p
, par
->height
);
430 bytestream_put_be24(&p
, par
->sample_aspect_ratio
.num
);
431 bytestream_put_be24(&p
, par
->sample_aspect_ratio
.den
);
432 if (st
->r_frame_rate
.num
> 0 && st
->r_frame_rate
.den
> 0) {
433 // OggVP8 requires pts to increase by 1 per visible frame, so use the least common
434 // multiple framerate if available.
435 av_log(s
, AV_LOG_DEBUG
, "Changing time base from %d/%d to %d/%d\n",
436 st
->time_base
.num
, st
->time_base
.den
,
437 st
->r_frame_rate
.den
, st
->r_frame_rate
.num
);
438 avpriv_set_pts_info(st
, 64, st
->r_frame_rate
.den
, st
->r_frame_rate
.num
);
440 bytestream_put_be32(&p
, st
->time_base
.den
);
441 bytestream_put_be32(&p
, st
->time_base
.num
);
443 /* optional second packet: VorbisComment */
444 if (av_dict_count(st
->metadata
)) {
445 p
= ogg_write_vorbiscomment(7, bitexact
, &oggstream
->header_len
[1], &st
->metadata
, 0, NULL
, 0);
447 return AVERROR(ENOMEM
);
448 oggstream
->header
[1] = p
;
449 bytestream_put_byte(&p
, 0x4f); // HDRID
450 bytestream_put_buffer(&p
, "VP80", 4); // Identifier
451 bytestream_put_byte(&p
, 2); // HDRTYP
452 bytestream_put_byte(&p
, 0x20);
455 oggstream
->isvp8
= 1;
460 static void ogg_write_pages(AVFormatContext
*s
, int flush
)
462 OGGContext
*ogg
= s
->priv_data
;
463 OGGPageList
*next
, *p
;
468 for (p
= ogg
->page_list
; p
; ) {
469 OGGStreamContext
*oggstream
=
470 s
->streams
[p
->page
.stream_index
]->priv_data
;
471 if (oggstream
->page_count
< 2 && !flush
)
473 ogg_write_page(s
, &p
->page
,
474 flush
== 1 && oggstream
->page_count
== 1 ? 4 : 0); // eos
482 static int ogg_init(AVFormatContext
*s
)
484 OGGContext
*ogg
= s
->priv_data
;
485 OGGStreamContext
*oggstream
= NULL
;
488 for (i
= 0; i
< s
->nb_streams
; i
++) {
489 AVStream
*st
= s
->streams
[i
];
490 unsigned serial_num
= i
+ ogg
->serial_offset
;
492 if (st
->codecpar
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
493 if (st
->codecpar
->codec_id
== AV_CODEC_ID_OPUS
)
494 /* Opus requires a fixed 48kHz clock */
495 avpriv_set_pts_info(st
, 64, 1, 48000);
497 avpriv_set_pts_info(st
, 64, 1, st
->codecpar
->sample_rate
);
500 if (st
->codecpar
->codec_id
!= AV_CODEC_ID_VORBIS
&&
501 st
->codecpar
->codec_id
!= AV_CODEC_ID_THEORA
&&
502 st
->codecpar
->codec_id
!= AV_CODEC_ID_SPEEX
&&
503 st
->codecpar
->codec_id
!= AV_CODEC_ID_FLAC
&&
504 st
->codecpar
->codec_id
!= AV_CODEC_ID_OPUS
&&
505 st
->codecpar
->codec_id
!= AV_CODEC_ID_VP8
) {
506 av_log(s
, AV_LOG_ERROR
, "Unsupported codec id in stream %d\n", i
);
507 return AVERROR(EINVAL
);
510 if ((!st
->codecpar
->extradata
|| !st
->codecpar
->extradata_size
) &&
511 st
->codecpar
->codec_id
!= AV_CODEC_ID_VP8
) {
512 av_log(s
, AV_LOG_ERROR
, "No extradata present\n");
513 return AVERROR_INVALIDDATA
;
515 oggstream
= av_mallocz(sizeof(*oggstream
));
517 return AVERROR(ENOMEM
);
519 oggstream
->page
.stream_index
= i
;
521 if (!(s
->flags
& AVFMT_FLAG_BITEXACT
))
523 serial_num
= av_get_random_seed();
524 for (j
= 0; j
< i
; j
++) {
525 OGGStreamContext
*sc
= s
->streams
[j
]->priv_data
;
526 if (serial_num
== sc
->serial_num
)
530 oggstream
->serial_num
= serial_num
;
532 av_dict_copy(&st
->metadata
, s
->metadata
, AV_DICT_DONT_OVERWRITE
);
534 st
->priv_data
= oggstream
;
535 if (st
->codecpar
->codec_id
== AV_CODEC_ID_FLAC
) {
536 int err
= ogg_build_flac_headers(st
->codecpar
, oggstream
,
537 s
->flags
& AVFMT_FLAG_BITEXACT
,
540 av_log(s
, AV_LOG_ERROR
, "Error writing FLAC headers\n");
543 } else if (st
->codecpar
->codec_id
== AV_CODEC_ID_SPEEX
) {
544 int err
= ogg_build_speex_headers(st
->codecpar
, oggstream
,
545 s
->flags
& AVFMT_FLAG_BITEXACT
,
548 av_log(s
, AV_LOG_ERROR
, "Error writing Speex headers\n");
551 } else if (st
->codecpar
->codec_id
== AV_CODEC_ID_OPUS
) {
552 int err
= ogg_build_opus_headers(st
->codecpar
, oggstream
,
553 s
->flags
& AVFMT_FLAG_BITEXACT
,
554 &st
->metadata
, s
->chapters
, s
->nb_chapters
);
556 av_log(s
, AV_LOG_ERROR
, "Error writing Opus headers\n");
559 } else if (st
->codecpar
->codec_id
== AV_CODEC_ID_VP8
) {
560 int err
= ogg_build_vp8_headers(s
, st
, oggstream
,
561 s
->flags
& AVFMT_FLAG_BITEXACT
);
563 av_log(s
, AV_LOG_ERROR
, "Error writing VP8 headers\n");
568 const char *cstr
= st
->codecpar
->codec_id
== AV_CODEC_ID_VORBIS
? "vorbis" : "theora";
569 int header_type
= st
->codecpar
->codec_id
== AV_CODEC_ID_VORBIS
? 3 : 0x81;
570 int framing_bit
= st
->codecpar
->codec_id
== AV_CODEC_ID_VORBIS
? 1 : 0;
572 if (avpriv_split_xiph_headers(st
->codecpar
->extradata
, st
->codecpar
->extradata_size
,
573 st
->codecpar
->codec_id
== AV_CODEC_ID_VORBIS
? 30 : 42,
574 (const uint8_t**)oggstream
->header
, oggstream
->header_len
) < 0) {
575 av_log(s
, AV_LOG_ERROR
, "Extradata corrupted\n");
576 oggstream
->header
[1] = NULL
;
577 return AVERROR_INVALIDDATA
;
580 p
= ogg_write_vorbiscomment(7, s
->flags
& AVFMT_FLAG_BITEXACT
,
581 &oggstream
->header_len
[1], &st
->metadata
,
582 framing_bit
, NULL
, 0);
583 oggstream
->header
[1] = p
;
585 return AVERROR(ENOMEM
);
587 bytestream_put_byte(&p
, header_type
);
588 bytestream_put_buffer(&p
, cstr
, 6);
590 if (st
->codecpar
->codec_id
== AV_CODEC_ID_THEORA
) {
591 int den
= AV_RB32(oggstream
->header
[0] + 22), num
= AV_RB32(oggstream
->header
[0] + 26);
592 /* Make sure to use time base stored in the Theora stream header to write
593 correct timestamps */
594 if (st
->time_base
.num
!= num
|| st
->time_base
.den
!= den
) {
595 av_log(s
, AV_LOG_DEBUG
, "Changing time base from %d/%d to %d/%d\n",
596 st
->time_base
.num
, st
->time_base
.den
, num
, den
);
597 avpriv_set_pts_info(st
, 64, num
, den
);
599 /** KFGSHIFT is the width of the less significant section of the granule position
600 The less significant section is the frame count since the last keyframe */
601 oggstream
->kfgshift
= ((oggstream
->header
[0][40]&3)<<3)|(oggstream
->header
[0][41]>>5);
602 oggstream
->vrev
= oggstream
->header
[0][9];
603 av_log(s
, AV_LOG_DEBUG
, "theora kfgshift %d, vrev %d\n",
604 oggstream
->kfgshift
, oggstream
->vrev
);
612 static int ogg_write_header(AVFormatContext
*s
)
614 OGGStreamContext
*oggstream
= NULL
;
617 for (j
= 0; j
< s
->nb_streams
; j
++) {
618 oggstream
= s
->streams
[j
]->priv_data
;
619 ogg_buffer_data(s
, s
->streams
[j
], oggstream
->header
[0],
620 oggstream
->header_len
[0], 0, 1);
621 oggstream
->page
.flags
|= 2; // bos
622 ogg_buffer_page(s
, oggstream
);
624 for (j
= 0; j
< s
->nb_streams
; j
++) {
625 AVStream
*st
= s
->streams
[j
];
626 oggstream
= st
->priv_data
;
627 for (i
= 1; i
< 3; i
++) {
628 if (oggstream
->header_len
[i
])
629 ogg_buffer_data(s
, st
, oggstream
->header
[i
],
630 oggstream
->header_len
[i
], 0, 1);
632 ogg_buffer_page(s
, oggstream
);
635 oggstream
->page
.start_granule
= AV_NOPTS_VALUE
;
637 ogg_write_pages(s
, 2);
642 static int ogg_write_packet_internal(AVFormatContext
*s
, AVPacket
*pkt
)
644 AVStream
*st
= s
->streams
[pkt
->stream_index
];
645 OGGStreamContext
*oggstream
= st
->priv_data
;
649 if (st
->codecpar
->codec_id
== AV_CODEC_ID_THEORA
) {
650 int64_t pts
= oggstream
->vrev
< 1 ? pkt
->pts
: pkt
->pts
+ pkt
->duration
;
652 if (pkt
->flags
& AV_PKT_FLAG_KEY
)
653 oggstream
->last_kf_pts
= pts
;
654 pframe_count
= pts
- oggstream
->last_kf_pts
;
655 // prevent frame count from overflow if key frame flag is not set
656 if (pframe_count
>= (1<<oggstream
->kfgshift
)) {
657 oggstream
->last_kf_pts
+= pframe_count
;
660 granule
= (oggstream
->last_kf_pts
<<oggstream
->kfgshift
) | pframe_count
;
661 } else if (st
->codecpar
->codec_id
== AV_CODEC_ID_OPUS
)
662 granule
= pkt
->pts
+ pkt
->duration
+
663 av_rescale_q(st
->codecpar
->initial_padding
,
664 (AVRational
){ 1, st
->codecpar
->sample_rate
},
666 else if (st
->codecpar
->codec_id
== AV_CODEC_ID_VP8
) {
667 int64_t pts
, invcnt
, dist
;
670 visible
= (pkt
->data
[0] >> 4) & 1;
671 pts
= pkt
->pts
+ pkt
->duration
;
672 invcnt
= (oggstream
->last_granule
>> 30) & 3;
673 invcnt
= visible
? 3 : (invcnt
== 3 ? 0 : invcnt
+ 1);
674 dist
= (pkt
->flags
& AV_PKT_FLAG_KEY
) ? 0 : ((oggstream
->last_granule
>> 3) & 0x07ffffff) + 1;
676 granule
= (pts
<< 32) | (invcnt
<< 30) | (dist
<< 3);
678 granule
= pkt
->pts
+ pkt
->duration
;
680 if (oggstream
->page
.start_granule
== AV_NOPTS_VALUE
)
681 oggstream
->page
.start_granule
= pkt
->pts
;
683 ret
= ogg_buffer_data(s
, st
, pkt
->data
, pkt
->size
, granule
, 0);
687 ogg_write_pages(s
, 0);
689 oggstream
->last_granule
= granule
;
694 static int ogg_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
699 return pkt
->size
|| !pkt
->side_data_elems
? ogg_write_packet_internal(s
, pkt
) : 0;
701 for (i
= 0; i
< s
->nb_streams
; i
++) {
702 OGGStreamContext
*oggstream
= s
->streams
[i
]->priv_data
;
703 if (oggstream
->page
.segments_count
)
704 ogg_buffer_page(s
, oggstream
);
707 ogg_write_pages(s
, 2);
711 static int ogg_write_trailer(AVFormatContext
*s
)
715 /* flush current page if needed */
716 for (i
= 0; i
< s
->nb_streams
; i
++) {
717 OGGStreamContext
*oggstream
= s
->streams
[i
]->priv_data
;
719 if (oggstream
->page
.segments_count
)
720 ogg_buffer_page(s
, oggstream
);
723 ogg_write_pages(s
, 1);
728 static void ogg_free(AVFormatContext
*s
)
730 OGGContext
*ogg
= s
->priv_data
;
731 OGGPageList
*p
= ogg
->page_list
;
734 for (i
= 0; i
< s
->nb_streams
; i
++) {
735 AVStream
*st
= s
->streams
[i
];
736 OGGStreamContext
*oggstream
= st
->priv_data
;
739 if (st
->codecpar
->codec_id
== AV_CODEC_ID_FLAC
||
740 st
->codecpar
->codec_id
== AV_CODEC_ID_SPEEX
||
741 st
->codecpar
->codec_id
== AV_CODEC_ID_OPUS
||
742 st
->codecpar
->codec_id
== AV_CODEC_ID_VP8
) {
743 av_freep(&oggstream
->header
[0]);
745 av_freep(&oggstream
->header
[1]);
749 OGGPageList
*next
= p
->next
;
753 ogg
->page_list
= NULL
;
757 const FFOutputFormat ff_ogg_muxer
= {
759 .p
.long_name
= NULL_IF_CONFIG_SMALL("Ogg"),
760 .p
.mime_type
= "application/ogg",
761 .p
.extensions
= "ogg"
762 #if !CONFIG_OGV_MUXER
765 #if !CONFIG_SPX_MUXER
768 #if !CONFIG_OPUS_MUXER
772 .priv_data_size
= sizeof(OGGContext
),
773 .p
.audio_codec
= CONFIG_LIBVORBIS_ENCODER
?
774 AV_CODEC_ID_VORBIS
: AV_CODEC_ID_FLAC
,
775 .p
.video_codec
= AV_CODEC_ID_THEORA
,
777 .write_header
= ogg_write_header
,
778 .write_packet
= ogg_write_packet
,
779 .write_trailer
= ogg_write_trailer
,
781 .p
.flags
= AVFMT_TS_NEGATIVE
| AVFMT_TS_NONSTRICT
,
782 .p
.priv_class
= &ogg_muxer_class
,
783 .flags_internal
= FF_OFMT_FLAG_ALLOW_FLUSH
,
788 const FFOutputFormat ff_oga_muxer
= {
790 .p
.long_name
= NULL_IF_CONFIG_SMALL("Ogg Audio"),
791 .p
.mime_type
= "audio/ogg",
792 .p
.extensions
= "oga",
793 .priv_data_size
= sizeof(OGGContext
),
794 .p
.audio_codec
= AV_CODEC_ID_FLAC
,
796 .write_header
= ogg_write_header
,
797 .write_packet
= ogg_write_packet
,
798 .write_trailer
= ogg_write_trailer
,
800 .p
.flags
= AVFMT_TS_NEGATIVE
,
801 .p
.priv_class
= &ogg_muxer_class
,
802 .flags_internal
= FF_OFMT_FLAG_ALLOW_FLUSH
,
807 const FFOutputFormat ff_ogv_muxer
= {
809 .p
.long_name
= NULL_IF_CONFIG_SMALL("Ogg Video"),
810 .p
.mime_type
= "video/ogg",
811 .p
.extensions
= "ogv",
812 .priv_data_size
= sizeof(OGGContext
),
813 .p
.audio_codec
= CONFIG_LIBVORBIS_ENCODER
?
814 AV_CODEC_ID_VORBIS
: AV_CODEC_ID_FLAC
,
815 .p
.video_codec
= CONFIG_LIBTHEORA_ENCODER
?
816 AV_CODEC_ID_THEORA
: AV_CODEC_ID_VP8
,
818 .write_header
= ogg_write_header
,
819 .write_packet
= ogg_write_packet
,
820 .write_trailer
= ogg_write_trailer
,
822 .p
.flags
= AVFMT_TS_NEGATIVE
| AVFMT_TS_NONSTRICT
,
823 .p
.priv_class
= &ogg_muxer_class
,
824 .flags_internal
= FF_OFMT_FLAG_ALLOW_FLUSH
,
829 const FFOutputFormat ff_spx_muxer
= {
831 .p
.long_name
= NULL_IF_CONFIG_SMALL("Ogg Speex"),
832 .p
.mime_type
= "audio/ogg",
833 .p
.extensions
= "spx",
834 .priv_data_size
= sizeof(OGGContext
),
835 .p
.audio_codec
= AV_CODEC_ID_SPEEX
,
837 .write_header
= ogg_write_header
,
838 .write_packet
= ogg_write_packet
,
839 .write_trailer
= ogg_write_trailer
,
841 .p
.flags
= AVFMT_TS_NEGATIVE
,
842 .p
.priv_class
= &ogg_muxer_class
,
843 .flags_internal
= FF_OFMT_FLAG_ALLOW_FLUSH
,
847 #if CONFIG_OPUS_MUXER
848 const FFOutputFormat ff_opus_muxer
= {
850 .p
.long_name
= NULL_IF_CONFIG_SMALL("Ogg Opus"),
851 .p
.mime_type
= "audio/ogg",
852 .p
.extensions
= "opus",
853 .priv_data_size
= sizeof(OGGContext
),
854 .p
.audio_codec
= AV_CODEC_ID_OPUS
,
856 .write_header
= ogg_write_header
,
857 .write_packet
= ogg_write_packet
,
858 .write_trailer
= ogg_write_trailer
,
860 .p
.flags
= AVFMT_TS_NEGATIVE
,
861 .p
.priv_class
= &ogg_muxer_class
,
862 .flags_internal
= FF_OFMT_FLAG_ALLOW_FLUSH
,