annotate ffmpeg/libavformat/oggenc.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Ogg muxer
yading@11 3 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr>
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 #include "libavutil/crc.h"
yading@11 23 #include "libavutil/opt.h"
yading@11 24 #include "libavutil/mathematics.h"
yading@11 25 #include "libavutil/opt.h"
yading@11 26 #include "libavutil/random_seed.h"
yading@11 27 #include "libavcodec/xiph.h"
yading@11 28 #include "libavcodec/bytestream.h"
yading@11 29 #include "libavcodec/flac.h"
yading@11 30 #include "avformat.h"
yading@11 31 #include "avio_internal.h"
yading@11 32 #include "internal.h"
yading@11 33 #include "vorbiscomment.h"
yading@11 34
yading@11 35 #define MAX_PAGE_SIZE 65025
yading@11 36
yading@11 37 typedef struct {
yading@11 38 int64_t start_granule;
yading@11 39 int64_t granule;
yading@11 40 int stream_index;
yading@11 41 uint8_t flags;
yading@11 42 uint8_t segments_count;
yading@11 43 uint8_t segments[255];
yading@11 44 uint8_t data[MAX_PAGE_SIZE];
yading@11 45 uint16_t size;
yading@11 46 } OGGPage;
yading@11 47
yading@11 48 typedef struct {
yading@11 49 unsigned page_counter;
yading@11 50 uint8_t *header[3];
yading@11 51 int header_len[3];
yading@11 52 /** for theora granule */
yading@11 53 int kfgshift;
yading@11 54 int64_t last_kf_pts;
yading@11 55 int vrev;
yading@11 56 int eos;
yading@11 57 unsigned page_count; ///< number of page buffered
yading@11 58 OGGPage page; ///< current page
yading@11 59 unsigned serial_num; ///< serial number
yading@11 60 int64_t last_granule; ///< last packet granule
yading@11 61 } OGGStreamContext;
yading@11 62
yading@11 63 typedef struct OGGPageList {
yading@11 64 OGGPage page;
yading@11 65 struct OGGPageList *next;
yading@11 66 } OGGPageList;
yading@11 67
yading@11 68 typedef struct {
yading@11 69 const AVClass *class;
yading@11 70 OGGPageList *page_list;
yading@11 71 int pref_size; ///< preferred page size (0 => fill all segments)
yading@11 72 int64_t pref_duration; ///< preferred page duration (0 => fill all segments)
yading@11 73 } OGGContext;
yading@11 74
yading@11 75 #define OFFSET(x) offsetof(OGGContext, x)
yading@11 76 #define PARAM AV_OPT_FLAG_ENCODING_PARAM
yading@11 77
yading@11 78 static const AVOption options[] = {
yading@11 79 { "oggpagesize", "Set preferred Ogg page size.",
yading@11 80 offsetof(OGGContext, pref_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, MAX_PAGE_SIZE, AV_OPT_FLAG_ENCODING_PARAM},
yading@11 81 { "pagesize", "preferred page size in bytes (deprecated)",
yading@11 82 OFFSET(pref_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, MAX_PAGE_SIZE, PARAM },
yading@11 83 { "page_duration", "preferred page duration, in microseconds",
yading@11 84 OFFSET(pref_duration), AV_OPT_TYPE_INT64, { .i64 = 1000000 }, 0, INT64_MAX, PARAM },
yading@11 85 { NULL },
yading@11 86 };
yading@11 87
yading@11 88 static const AVClass ogg_muxer_class = {
yading@11 89 .class_name = "Ogg muxer",
yading@11 90 .item_name = av_default_item_name,
yading@11 91 .option = options,
yading@11 92 .version = LIBAVUTIL_VERSION_INT,
yading@11 93 };
yading@11 94
yading@11 95
yading@11 96 static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset)
yading@11 97 {
yading@11 98 int64_t pos = avio_tell(pb);
yading@11 99 uint32_t checksum = ffio_get_checksum(pb);
yading@11 100 avio_seek(pb, crc_offset, SEEK_SET);
yading@11 101 avio_wb32(pb, checksum);
yading@11 102 avio_seek(pb, pos, SEEK_SET);
yading@11 103 }
yading@11 104
yading@11 105 static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags)
yading@11 106 {
yading@11 107 OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data;
yading@11 108 AVIOContext *pb;
yading@11 109 int64_t crc_offset;
yading@11 110 int ret, size;
yading@11 111 uint8_t *buf;
yading@11 112
yading@11 113 ret = avio_open_dyn_buf(&pb);
yading@11 114 if (ret < 0)
yading@11 115 return ret;
yading@11 116 ffio_init_checksum(pb, ff_crc04C11DB7_update, 0);
yading@11 117 ffio_wfourcc(pb, "OggS");
yading@11 118 avio_w8(pb, 0);
yading@11 119 avio_w8(pb, page->flags | extra_flags);
yading@11 120 avio_wl64(pb, page->granule);
yading@11 121 avio_wl32(pb, oggstream->serial_num);
yading@11 122 avio_wl32(pb, oggstream->page_counter++);
yading@11 123 crc_offset = avio_tell(pb);
yading@11 124 avio_wl32(pb, 0); // crc
yading@11 125 avio_w8(pb, page->segments_count);
yading@11 126 avio_write(pb, page->segments, page->segments_count);
yading@11 127 avio_write(pb, page->data, page->size);
yading@11 128
yading@11 129 ogg_update_checksum(s, pb, crc_offset);
yading@11 130 avio_flush(pb);
yading@11 131
yading@11 132 size = avio_close_dyn_buf(pb, &buf);
yading@11 133 if (size < 0)
yading@11 134 return size;
yading@11 135
yading@11 136 avio_write(s->pb, buf, size);
yading@11 137 avio_flush(s->pb);
yading@11 138 av_free(buf);
yading@11 139 oggstream->page_count--;
yading@11 140 return 0;
yading@11 141 }
yading@11 142
yading@11 143 static int ogg_key_granule(OGGStreamContext *oggstream, int64_t granule)
yading@11 144 {
yading@11 145 return oggstream->kfgshift && !(granule & ((1<<oggstream->kfgshift)-1));
yading@11 146 }
yading@11 147
yading@11 148 static int64_t ogg_granule_to_timestamp(OGGStreamContext *oggstream, int64_t granule)
yading@11 149 {
yading@11 150 if (oggstream->kfgshift)
yading@11 151 return (granule>>oggstream->kfgshift) +
yading@11 152 (granule & ((1<<oggstream->kfgshift)-1));
yading@11 153 else
yading@11 154 return granule;
yading@11 155 }
yading@11 156
yading@11 157 static int ogg_compare_granule(AVFormatContext *s, OGGPage *next, OGGPage *page)
yading@11 158 {
yading@11 159 AVStream *st2 = s->streams[next->stream_index];
yading@11 160 AVStream *st = s->streams[page->stream_index];
yading@11 161 int64_t next_granule, cur_granule;
yading@11 162
yading@11 163 if (next->granule == -1 || page->granule == -1)
yading@11 164 return 0;
yading@11 165
yading@11 166 next_granule = av_rescale_q(ogg_granule_to_timestamp(st2->priv_data, next->granule),
yading@11 167 st2->time_base, AV_TIME_BASE_Q);
yading@11 168 cur_granule = av_rescale_q(ogg_granule_to_timestamp(st->priv_data, page->granule),
yading@11 169 st ->time_base, AV_TIME_BASE_Q);
yading@11 170 return next_granule > cur_granule;
yading@11 171 }
yading@11 172
yading@11 173 static int ogg_reset_cur_page(OGGStreamContext *oggstream)
yading@11 174 {
yading@11 175 oggstream->page.granule = -1;
yading@11 176 oggstream->page.flags = 0;
yading@11 177 oggstream->page.segments_count = 0;
yading@11 178 oggstream->page.size = 0;
yading@11 179 return 0;
yading@11 180 }
yading@11 181
yading@11 182 static int ogg_buffer_page(AVFormatContext *s, OGGStreamContext *oggstream)
yading@11 183 {
yading@11 184 OGGContext *ogg = s->priv_data;
yading@11 185 OGGPageList **p = &ogg->page_list;
yading@11 186 OGGPageList *l = av_mallocz(sizeof(*l));
yading@11 187
yading@11 188 if (!l)
yading@11 189 return AVERROR(ENOMEM);
yading@11 190 l->page = oggstream->page;
yading@11 191
yading@11 192 oggstream->page.start_granule = oggstream->page.granule;
yading@11 193 oggstream->page_count++;
yading@11 194 ogg_reset_cur_page(oggstream);
yading@11 195
yading@11 196 while (*p) {
yading@11 197 if (ogg_compare_granule(s, &(*p)->page, &l->page))
yading@11 198 break;
yading@11 199 p = &(*p)->next;
yading@11 200 }
yading@11 201 l->next = *p;
yading@11 202 *p = l;
yading@11 203
yading@11 204 return 0;
yading@11 205 }
yading@11 206
yading@11 207 static int ogg_buffer_data(AVFormatContext *s, AVStream *st,
yading@11 208 uint8_t *data, unsigned size, int64_t granule,
yading@11 209 int header)
yading@11 210 {
yading@11 211 OGGStreamContext *oggstream = st->priv_data;
yading@11 212 OGGContext *ogg = s->priv_data;
yading@11 213 int total_segments = size / 255 + 1;
yading@11 214 uint8_t *p = data;
yading@11 215 int i, segments, len, flush = 0;
yading@11 216
yading@11 217 // Handles VFR by flushing page because this frame needs to have a timestamp
yading@11 218 // For theora, keyframes also need to have a timestamp to correctly mark
yading@11 219 // them as such, otherwise seeking will not work correctly at the very
yading@11 220 // least with old libogg versions.
yading@11 221 // Do not try to flush header packets though, that will create broken files.
yading@11 222 if (st->codec->codec_id == AV_CODEC_ID_THEORA && !header &&
yading@11 223 (ogg_granule_to_timestamp(oggstream, granule) >
yading@11 224 ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1 ||
yading@11 225 ogg_key_granule(oggstream, granule))) {
yading@11 226 if (oggstream->page.granule != -1)
yading@11 227 ogg_buffer_page(s, oggstream);
yading@11 228 flush = 1;
yading@11 229 }
yading@11 230
yading@11 231 // avoid a continued page
yading@11 232 if (!header && oggstream->page.size > 0 &&
yading@11 233 MAX_PAGE_SIZE - oggstream->page.size < size) {
yading@11 234 ogg_buffer_page(s, oggstream);
yading@11 235 }
yading@11 236
yading@11 237 for (i = 0; i < total_segments; ) {
yading@11 238 OGGPage *page = &oggstream->page;
yading@11 239
yading@11 240 segments = FFMIN(total_segments - i, 255 - page->segments_count);
yading@11 241
yading@11 242 if (i && !page->segments_count)
yading@11 243 page->flags |= 1; // continued packet
yading@11 244
yading@11 245 memset(page->segments+page->segments_count, 255, segments - 1);
yading@11 246 page->segments_count += segments - 1;
yading@11 247
yading@11 248 len = FFMIN(size, segments*255);
yading@11 249 page->segments[page->segments_count++] = len - (segments-1)*255;
yading@11 250 memcpy(page->data+page->size, p, len);
yading@11 251 p += len;
yading@11 252 size -= len;
yading@11 253 i += segments;
yading@11 254 page->size += len;
yading@11 255
yading@11 256 if (i == total_segments)
yading@11 257 page->granule = granule;
yading@11 258
yading@11 259 if (!header) {
yading@11 260 AVStream *st = s->streams[page->stream_index];
yading@11 261
yading@11 262 int64_t start = av_rescale_q(page->start_granule, st->time_base,
yading@11 263 AV_TIME_BASE_Q);
yading@11 264 int64_t next = av_rescale_q(page->granule, st->time_base,
yading@11 265 AV_TIME_BASE_Q);
yading@11 266
yading@11 267 if (page->segments_count == 255 ||
yading@11 268 (ogg->pref_size > 0 && page->size >= ogg->pref_size) ||
yading@11 269 (ogg->pref_duration > 0 && next - start >= ogg->pref_duration)) {
yading@11 270 ogg_buffer_page(s, oggstream);
yading@11 271 }
yading@11 272 }
yading@11 273 }
yading@11 274
yading@11 275 if (flush && oggstream->page.granule != -1)
yading@11 276 ogg_buffer_page(s, oggstream);
yading@11 277
yading@11 278 return 0;
yading@11 279 }
yading@11 280
yading@11 281 static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact,
yading@11 282 int *header_len, AVDictionary **m, int framing_bit)
yading@11 283 {
yading@11 284 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
yading@11 285 int size;
yading@11 286 uint8_t *p, *p0;
yading@11 287 unsigned int count;
yading@11 288
yading@11 289 ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
yading@11 290
yading@11 291 size = offset + ff_vorbiscomment_length(*m, vendor, &count) + framing_bit;
yading@11 292 p = av_mallocz(size);
yading@11 293 if (!p)
yading@11 294 return NULL;
yading@11 295 p0 = p;
yading@11 296
yading@11 297 p += offset;
yading@11 298 ff_vorbiscomment_write(&p, m, vendor, count);
yading@11 299 if (framing_bit)
yading@11 300 bytestream_put_byte(&p, 1);
yading@11 301
yading@11 302 *header_len = size;
yading@11 303 return p0;
yading@11 304 }
yading@11 305
yading@11 306 static int ogg_build_flac_headers(AVCodecContext *avctx,
yading@11 307 OGGStreamContext *oggstream, int bitexact,
yading@11 308 AVDictionary **m)
yading@11 309 {
yading@11 310 enum FLACExtradataFormat format;
yading@11 311 uint8_t *streaminfo;
yading@11 312 uint8_t *p;
yading@11 313
yading@11 314 if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo))
yading@11 315 return -1;
yading@11 316
yading@11 317 // first packet: STREAMINFO
yading@11 318 oggstream->header_len[0] = 51;
yading@11 319 oggstream->header[0] = av_mallocz(51); // per ogg flac specs
yading@11 320 p = oggstream->header[0];
yading@11 321 if (!p)
yading@11 322 return AVERROR(ENOMEM);
yading@11 323 bytestream_put_byte(&p, 0x7F);
yading@11 324 bytestream_put_buffer(&p, "FLAC", 4);
yading@11 325 bytestream_put_byte(&p, 1); // major version
yading@11 326 bytestream_put_byte(&p, 0); // minor version
yading@11 327 bytestream_put_be16(&p, 1); // headers packets without this one
yading@11 328 bytestream_put_buffer(&p, "fLaC", 4);
yading@11 329 bytestream_put_byte(&p, 0x00); // streaminfo
yading@11 330 bytestream_put_be24(&p, 34);
yading@11 331 bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE);
yading@11 332
yading@11 333 // second packet: VorbisComment
yading@11 334 p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m, 0);
yading@11 335 if (!p)
yading@11 336 return AVERROR(ENOMEM);
yading@11 337 oggstream->header[1] = p;
yading@11 338 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment
yading@11 339 bytestream_put_be24(&p, oggstream->header_len[1] - 4);
yading@11 340
yading@11 341 return 0;
yading@11 342 }
yading@11 343
yading@11 344 #define SPEEX_HEADER_SIZE 80
yading@11 345
yading@11 346 static int ogg_build_speex_headers(AVCodecContext *avctx,
yading@11 347 OGGStreamContext *oggstream, int bitexact,
yading@11 348 AVDictionary **m)
yading@11 349 {
yading@11 350 uint8_t *p;
yading@11 351
yading@11 352 if (avctx->extradata_size < SPEEX_HEADER_SIZE)
yading@11 353 return -1;
yading@11 354
yading@11 355 // first packet: Speex header
yading@11 356 p = av_mallocz(SPEEX_HEADER_SIZE);
yading@11 357 if (!p)
yading@11 358 return AVERROR(ENOMEM);
yading@11 359 oggstream->header[0] = p;
yading@11 360 oggstream->header_len[0] = SPEEX_HEADER_SIZE;
yading@11 361 bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE);
yading@11 362 AV_WL32(&oggstream->header[0][68], 0); // set extra_headers to 0
yading@11 363
yading@11 364 // second packet: VorbisComment
yading@11 365 p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1], m, 0);
yading@11 366 if (!p)
yading@11 367 return AVERROR(ENOMEM);
yading@11 368 oggstream->header[1] = p;
yading@11 369
yading@11 370 return 0;
yading@11 371 }
yading@11 372
yading@11 373 #define OPUS_HEADER_SIZE 19
yading@11 374
yading@11 375 static int ogg_build_opus_headers(AVCodecContext *avctx,
yading@11 376 OGGStreamContext *oggstream, int bitexact,
yading@11 377 AVDictionary **m)
yading@11 378 {
yading@11 379 uint8_t *p;
yading@11 380
yading@11 381 if (avctx->extradata_size < OPUS_HEADER_SIZE)
yading@11 382 return -1;
yading@11 383
yading@11 384 /* first packet: Opus header */
yading@11 385 p = av_mallocz(avctx->extradata_size);
yading@11 386 if (!p)
yading@11 387 return AVERROR(ENOMEM);
yading@11 388 oggstream->header[0] = p;
yading@11 389 oggstream->header_len[0] = avctx->extradata_size;
yading@11 390 bytestream_put_buffer(&p, avctx->extradata, avctx->extradata_size);
yading@11 391
yading@11 392 /* second packet: VorbisComment */
yading@11 393 p = ogg_write_vorbiscomment(8, bitexact, &oggstream->header_len[1], m, 0);
yading@11 394 if (!p)
yading@11 395 return AVERROR(ENOMEM);
yading@11 396 oggstream->header[1] = p;
yading@11 397 bytestream_put_buffer(&p, "OpusTags", 8);
yading@11 398
yading@11 399 return 0;
yading@11 400 }
yading@11 401
yading@11 402 static int ogg_write_header(AVFormatContext *s)
yading@11 403 {
yading@11 404 OGGContext *ogg = s->priv_data;
yading@11 405 OGGStreamContext *oggstream = NULL;
yading@11 406 int i, j;
yading@11 407
yading@11 408 if (ogg->pref_size)
yading@11 409 av_log(s, AV_LOG_WARNING, "The pagesize option is deprecated\n");
yading@11 410
yading@11 411 for (i = 0; i < s->nb_streams; i++) {
yading@11 412 AVStream *st = s->streams[i];
yading@11 413 unsigned serial_num = i;
yading@11 414
yading@11 415 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
yading@11 416 if (st->codec->codec_id == AV_CODEC_ID_OPUS)
yading@11 417 /* Opus requires a fixed 48kHz clock */
yading@11 418 avpriv_set_pts_info(st, 64, 1, 48000);
yading@11 419 else
yading@11 420 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
yading@11 421 } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
yading@11 422 avpriv_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
yading@11 423 if (st->codec->codec_id != AV_CODEC_ID_VORBIS &&
yading@11 424 st->codec->codec_id != AV_CODEC_ID_THEORA &&
yading@11 425 st->codec->codec_id != AV_CODEC_ID_SPEEX &&
yading@11 426 st->codec->codec_id != AV_CODEC_ID_FLAC &&
yading@11 427 st->codec->codec_id != AV_CODEC_ID_OPUS) {
yading@11 428 av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i);
yading@11 429 return -1;
yading@11 430 }
yading@11 431
yading@11 432 if (!st->codec->extradata || !st->codec->extradata_size) {
yading@11 433 av_log(s, AV_LOG_ERROR, "No extradata present\n");
yading@11 434 return -1;
yading@11 435 }
yading@11 436 oggstream = av_mallocz(sizeof(*oggstream));
yading@11 437 oggstream->page.stream_index = i;
yading@11 438
yading@11 439 if (!(st->codec->flags & CODEC_FLAG_BITEXACT))
yading@11 440 do {
yading@11 441 serial_num = av_get_random_seed();
yading@11 442 for (j = 0; j < i; j++) {
yading@11 443 OGGStreamContext *sc = s->streams[j]->priv_data;
yading@11 444 if (serial_num == sc->serial_num)
yading@11 445 break;
yading@11 446 }
yading@11 447 } while (j < i);
yading@11 448 oggstream->serial_num = serial_num;
yading@11 449
yading@11 450 st->priv_data = oggstream;
yading@11 451 if (st->codec->codec_id == AV_CODEC_ID_FLAC) {
yading@11 452 int err = ogg_build_flac_headers(st->codec, oggstream,
yading@11 453 st->codec->flags & CODEC_FLAG_BITEXACT,
yading@11 454 &s->metadata);
yading@11 455 if (err) {
yading@11 456 av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n");
yading@11 457 av_freep(&st->priv_data);
yading@11 458 return err;
yading@11 459 }
yading@11 460 } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) {
yading@11 461 int err = ogg_build_speex_headers(st->codec, oggstream,
yading@11 462 st->codec->flags & CODEC_FLAG_BITEXACT,
yading@11 463 &s->metadata);
yading@11 464 if (err) {
yading@11 465 av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n");
yading@11 466 av_freep(&st->priv_data);
yading@11 467 return err;
yading@11 468 }
yading@11 469 } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
yading@11 470 int err = ogg_build_opus_headers(st->codec, oggstream,
yading@11 471 st->codec->flags & CODEC_FLAG_BITEXACT,
yading@11 472 &s->metadata);
yading@11 473 if (err) {
yading@11 474 av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n");
yading@11 475 av_freep(&st->priv_data);
yading@11 476 return err;
yading@11 477 }
yading@11 478 } else {
yading@11 479 uint8_t *p;
yading@11 480 const char *cstr = st->codec->codec_id == AV_CODEC_ID_VORBIS ? "vorbis" : "theora";
yading@11 481 int header_type = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 3 : 0x81;
yading@11 482 int framing_bit = st->codec->codec_id == AV_CODEC_ID_VORBIS ? 1 : 0;
yading@11 483
yading@11 484 if (avpriv_split_xiph_headers(st->codec->extradata, st->codec->extradata_size,
yading@11 485 st->codec->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42,
yading@11 486 oggstream->header, oggstream->header_len) < 0) {
yading@11 487 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
yading@11 488 av_freep(&st->priv_data);
yading@11 489 return -1;
yading@11 490 }
yading@11 491
yading@11 492 p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT,
yading@11 493 &oggstream->header_len[1], &s->metadata,
yading@11 494 framing_bit);
yading@11 495 oggstream->header[1] = p;
yading@11 496 if (!p)
yading@11 497 return AVERROR(ENOMEM);
yading@11 498
yading@11 499 bytestream_put_byte(&p, header_type);
yading@11 500 bytestream_put_buffer(&p, cstr, 6);
yading@11 501
yading@11 502 if (st->codec->codec_id == AV_CODEC_ID_THEORA) {
yading@11 503 /** KFGSHIFT is the width of the less significant section of the granule position
yading@11 504 The less significant section is the frame count since the last keyframe */
yading@11 505 oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5);
yading@11 506 oggstream->vrev = oggstream->header[0][9];
yading@11 507 av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n",
yading@11 508 oggstream->kfgshift, oggstream->vrev);
yading@11 509 }
yading@11 510 }
yading@11 511 }
yading@11 512
yading@11 513 for (j = 0; j < s->nb_streams; j++) {
yading@11 514 OGGStreamContext *oggstream = s->streams[j]->priv_data;
yading@11 515 ogg_buffer_data(s, s->streams[j], oggstream->header[0],
yading@11 516 oggstream->header_len[0], 0, 1);
yading@11 517 oggstream->page.flags |= 2; // bos
yading@11 518 ogg_buffer_page(s, oggstream);
yading@11 519 }
yading@11 520 for (j = 0; j < s->nb_streams; j++) {
yading@11 521 AVStream *st = s->streams[j];
yading@11 522 OGGStreamContext *oggstream = st->priv_data;
yading@11 523 for (i = 1; i < 3; i++) {
yading@11 524 if (oggstream->header_len[i])
yading@11 525 ogg_buffer_data(s, st, oggstream->header[i],
yading@11 526 oggstream->header_len[i], 0, 1);
yading@11 527 }
yading@11 528 ogg_buffer_page(s, oggstream);
yading@11 529 }
yading@11 530
yading@11 531 oggstream->page.start_granule = AV_NOPTS_VALUE;
yading@11 532
yading@11 533 return 0;
yading@11 534 }
yading@11 535
yading@11 536 static void ogg_write_pages(AVFormatContext *s, int flush)
yading@11 537 {
yading@11 538 OGGContext *ogg = s->priv_data;
yading@11 539 OGGPageList *next, *p;
yading@11 540
yading@11 541 if (!ogg->page_list)
yading@11 542 return;
yading@11 543
yading@11 544 for (p = ogg->page_list; p; ) {
yading@11 545 OGGStreamContext *oggstream =
yading@11 546 s->streams[p->page.stream_index]->priv_data;
yading@11 547 if (oggstream->page_count < 2 && !flush)
yading@11 548 break;
yading@11 549 ogg_write_page(s, &p->page,
yading@11 550 flush && oggstream->page_count == 1 ? 4 : 0); // eos
yading@11 551 next = p->next;
yading@11 552 av_freep(&p);
yading@11 553 p = next;
yading@11 554 }
yading@11 555 ogg->page_list = p;
yading@11 556 }
yading@11 557
yading@11 558 static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt)
yading@11 559 {
yading@11 560 AVStream *st = s->streams[pkt->stream_index];
yading@11 561 OGGStreamContext *oggstream = st->priv_data;
yading@11 562 int ret;
yading@11 563 int64_t granule;
yading@11 564
yading@11 565 if (st->codec->codec_id == AV_CODEC_ID_THEORA) {
yading@11 566 int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration;
yading@11 567 int pframe_count;
yading@11 568 if (pkt->flags & AV_PKT_FLAG_KEY)
yading@11 569 oggstream->last_kf_pts = pts;
yading@11 570 pframe_count = pts - oggstream->last_kf_pts;
yading@11 571 // prevent frame count from overflow if key frame flag is not set
yading@11 572 if (pframe_count >= (1<<oggstream->kfgshift)) {
yading@11 573 oggstream->last_kf_pts += pframe_count;
yading@11 574 pframe_count = 0;
yading@11 575 }
yading@11 576 granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count;
yading@11 577 } else if (st->codec->codec_id == AV_CODEC_ID_OPUS)
yading@11 578 granule = pkt->pts + pkt->duration + av_rescale_q(st->codec->delay, (AVRational){ 1, st->codec->sample_rate }, st->time_base);
yading@11 579 else
yading@11 580 granule = pkt->pts + pkt->duration;
yading@11 581
yading@11 582 if (oggstream->page.start_granule == AV_NOPTS_VALUE)
yading@11 583 oggstream->page.start_granule = pkt->pts;
yading@11 584
yading@11 585 ret = ogg_buffer_data(s, st, pkt->data, pkt->size, granule, 0);
yading@11 586 if (ret < 0)
yading@11 587 return ret;
yading@11 588
yading@11 589 ogg_write_pages(s, 0);
yading@11 590
yading@11 591 oggstream->last_granule = granule;
yading@11 592
yading@11 593 return 0;
yading@11 594 }
yading@11 595
yading@11 596 static int ogg_write_trailer(AVFormatContext *s)
yading@11 597 {
yading@11 598 int i;
yading@11 599
yading@11 600 /* flush current page if needed */
yading@11 601 for (i = 0; i < s->nb_streams; i++) {
yading@11 602 OGGStreamContext *oggstream = s->streams[i]->priv_data;
yading@11 603
yading@11 604 if (oggstream->page.size > 0)
yading@11 605 ogg_buffer_page(s, oggstream);
yading@11 606 }
yading@11 607
yading@11 608 ogg_write_pages(s, 1);
yading@11 609
yading@11 610 for (i = 0; i < s->nb_streams; i++) {
yading@11 611 AVStream *st = s->streams[i];
yading@11 612 OGGStreamContext *oggstream = st->priv_data;
yading@11 613 if (st->codec->codec_id == AV_CODEC_ID_FLAC ||
yading@11 614 st->codec->codec_id == AV_CODEC_ID_SPEEX ||
yading@11 615 st->codec->codec_id == AV_CODEC_ID_OPUS) {
yading@11 616 av_freep(&oggstream->header[0]);
yading@11 617 }
yading@11 618 av_freep(&oggstream->header[1]);
yading@11 619 av_freep(&st->priv_data);
yading@11 620 }
yading@11 621 return 0;
yading@11 622 }
yading@11 623
yading@11 624 AVOutputFormat ff_ogg_muxer = {
yading@11 625 .name = "ogg",
yading@11 626 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
yading@11 627 .mime_type = "application/ogg",
yading@11 628 .extensions = "ogg,ogv,spx,opus",
yading@11 629 .priv_data_size = sizeof(OGGContext),
yading@11 630 .audio_codec = AV_CODEC_ID_FLAC,
yading@11 631 .video_codec = AV_CODEC_ID_THEORA,
yading@11 632 .write_header = ogg_write_header,
yading@11 633 .write_packet = ogg_write_packet,
yading@11 634 .write_trailer = ogg_write_trailer,
yading@11 635 .priv_class = &ogg_muxer_class,
yading@11 636 };