| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Ogg muxer | 2 * Ogg muxer |
| 3 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr> | 3 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr> |
| 4 * | 4 * |
| 5 * This file is part of FFmpeg. | 5 * This file is part of FFmpeg. |
| 6 * | 6 * |
| 7 * FFmpeg is free software; you can redistribute it and/or | 7 * FFmpeg is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 page->granule = granule; | 199 page->granule = granule; |
| 200 | 200 |
| 201 if (page->segments_count == 255) { | 201 if (page->segments_count == 255) { |
| 202 ogg_buffer_page(s, oggstream); | 202 ogg_buffer_page(s, oggstream); |
| 203 } | 203 } |
| 204 } | 204 } |
| 205 return 0; | 205 return 0; |
| 206 } | 206 } |
| 207 | 207 |
| 208 static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, | 208 static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, |
| 209 int *header_len, AVMetadata *m) | 209 int *header_len, AVMetadata *m, int fram
ing_bit) |
| 210 { | 210 { |
| 211 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; | 211 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; |
| 212 int size; | 212 int size; |
| 213 uint8_t *p, *p0; | 213 uint8_t *p, *p0; |
| 214 unsigned int count; | 214 unsigned int count; |
| 215 | 215 |
| 216 size = offset + ff_vorbiscomment_length(m, vendor, &count); | 216 size = offset + ff_vorbiscomment_length(m, vendor, &count) + framing_bit; |
| 217 p = av_mallocz(size); | 217 p = av_mallocz(size); |
| 218 if (!p) | 218 if (!p) |
| 219 return NULL; | 219 return NULL; |
| 220 p0 = p; | 220 p0 = p; |
| 221 | 221 |
| 222 p += offset; | 222 p += offset; |
| 223 ff_vorbiscomment_write(&p, m, vendor, count); | 223 ff_vorbiscomment_write(&p, m, vendor, count); |
| 224 if (framing_bit) |
| 225 bytestream_put_byte(&p, 1); |
| 224 | 226 |
| 225 *header_len = size; | 227 *header_len = size; |
| 226 return p0; | 228 return p0; |
| 227 } | 229 } |
| 228 | 230 |
| 229 static int ogg_build_flac_headers(AVCodecContext *avctx, | 231 static int ogg_build_flac_headers(AVCodecContext *avctx, |
| 230 OGGStreamContext *oggstream, int bitexact, | 232 OGGStreamContext *oggstream, int bitexact, |
| 231 AVMetadata *m) | 233 AVMetadata *m) |
| 232 { | 234 { |
| 233 enum FLACExtradataFormat format; | 235 enum FLACExtradataFormat format; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 247 bytestream_put_buffer(&p, "FLAC", 4); | 249 bytestream_put_buffer(&p, "FLAC", 4); |
| 248 bytestream_put_byte(&p, 1); // major version | 250 bytestream_put_byte(&p, 1); // major version |
| 249 bytestream_put_byte(&p, 0); // minor version | 251 bytestream_put_byte(&p, 0); // minor version |
| 250 bytestream_put_be16(&p, 1); // headers packets without this one | 252 bytestream_put_be16(&p, 1); // headers packets without this one |
| 251 bytestream_put_buffer(&p, "fLaC", 4); | 253 bytestream_put_buffer(&p, "fLaC", 4); |
| 252 bytestream_put_byte(&p, 0x00); // streaminfo | 254 bytestream_put_byte(&p, 0x00); // streaminfo |
| 253 bytestream_put_be24(&p, 34); | 255 bytestream_put_be24(&p, 34); |
| 254 bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE); | 256 bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE); |
| 255 | 257 |
| 256 // second packet: VorbisComment | 258 // second packet: VorbisComment |
| 257 p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m); | 259 p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m, 0); |
| 258 if (!p) | 260 if (!p) |
| 259 return AVERROR(ENOMEM); | 261 return AVERROR(ENOMEM); |
| 260 oggstream->header[1] = p; | 262 oggstream->header[1] = p; |
| 261 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment | 263 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment |
| 262 bytestream_put_be24(&p, oggstream->header_len[1] - 4); | 264 bytestream_put_be24(&p, oggstream->header_len[1] - 4); |
| 263 | 265 |
| 264 return 0; | 266 return 0; |
| 265 } | 267 } |
| 266 | 268 |
| 267 #define SPEEX_HEADER_SIZE 80 | 269 #define SPEEX_HEADER_SIZE 80 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 278 // first packet: Speex header | 280 // first packet: Speex header |
| 279 p = av_mallocz(SPEEX_HEADER_SIZE); | 281 p = av_mallocz(SPEEX_HEADER_SIZE); |
| 280 if (!p) | 282 if (!p) |
| 281 return AVERROR(ENOMEM); | 283 return AVERROR(ENOMEM); |
| 282 oggstream->header[0] = p; | 284 oggstream->header[0] = p; |
| 283 oggstream->header_len[0] = SPEEX_HEADER_SIZE; | 285 oggstream->header_len[0] = SPEEX_HEADER_SIZE; |
| 284 bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE); | 286 bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE); |
| 285 AV_WL32(&oggstream->header[0][68], 0); // set extra_headers to 0 | 287 AV_WL32(&oggstream->header[0][68], 0); // set extra_headers to 0 |
| 286 | 288 |
| 287 // second packet: VorbisComment | 289 // second packet: VorbisComment |
| 288 p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1], m); | 290 p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1], m, 0); |
| 289 if (!p) | 291 if (!p) |
| 290 return AVERROR(ENOMEM); | 292 return AVERROR(ENOMEM); |
| 291 oggstream->header[1] = p; | 293 oggstream->header[1] = p; |
| 292 | 294 |
| 293 return 0; | 295 return 0; |
| 294 } | 296 } |
| 295 | 297 |
| 296 static int ogg_write_header(AVFormatContext *s) | 298 static int ogg_write_header(AVFormatContext *s) |
| 297 { | 299 { |
| 298 OGGStreamContext *oggstream; | 300 OGGStreamContext *oggstream; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 } else if (st->codec->codec_id == CODEC_ID_SPEEX) { | 347 } else if (st->codec->codec_id == CODEC_ID_SPEEX) { |
| 346 int err = ogg_build_speex_headers(st->codec, oggstream, | 348 int err = ogg_build_speex_headers(st->codec, oggstream, |
| 347 st->codec->flags & CODEC_FLAG_BITE
XACT, | 349 st->codec->flags & CODEC_FLAG_BITE
XACT, |
| 348 s->metadata); | 350 s->metadata); |
| 349 if (err) { | 351 if (err) { |
| 350 av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); | 352 av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); |
| 351 av_freep(&st->priv_data); | 353 av_freep(&st->priv_data); |
| 352 return err; | 354 return err; |
| 353 } | 355 } |
| 354 } else { | 356 } else { |
| 357 uint8_t *p; |
| 358 char *cstr = st->codec->codec_id == CODEC_ID_VORBIS ? "vorbis" : "th
eora"; |
| 359 int header_type = st->codec->codec_id == CODEC_ID_VORBIS ? 3 : 0x81; |
| 360 int framing_bit = st->codec->codec_id == CODEC_ID_VORBIS ? 1 : 0; |
| 361 |
| 355 if (ff_split_xiph_headers(st->codec->extradata, st->codec->extradata
_size, | 362 if (ff_split_xiph_headers(st->codec->extradata, st->codec->extradata
_size, |
| 356 st->codec->codec_id == CODEC_ID_VORBIS ? 3
0 : 42, | 363 st->codec->codec_id == CODEC_ID_VORBIS ? 3
0 : 42, |
| 357 oggstream->header, oggstream->header_len)
< 0) { | 364 oggstream->header, oggstream->header_len)
< 0) { |
| 358 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n"); | 365 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n"); |
| 359 av_freep(&st->priv_data); | 366 av_freep(&st->priv_data); |
| 360 return -1; | 367 return -1; |
| 361 } | 368 } |
| 369 |
| 370 p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXAC
T, |
| 371 &oggstream->header_len[1], s->metadata, |
| 372 framing_bit); |
| 373 if (!p) |
| 374 return AVERROR(ENOMEM); |
| 375 |
| 376 oggstream->header[1] = p; |
| 377 bytestream_put_byte(&p, header_type); |
| 378 bytestream_put_buffer(&p, cstr, 6); |
| 379 |
| 362 if (st->codec->codec_id == CODEC_ID_THEORA) { | 380 if (st->codec->codec_id == CODEC_ID_THEORA) { |
| 363 /** KFGSHIFT is the width of the less significant section of the
granule position | 381 /** KFGSHIFT is the width of the less significant section of the
granule position |
| 364 The less significant section is the frame count since the la
st keyframe */ | 382 The less significant section is the frame count since the la
st keyframe */ |
| 365 oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstre
am->header[0][41]>>5); | 383 oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstre
am->header[0][41]>>5); |
| 366 oggstream->vrev = oggstream->header[0][9]; | 384 oggstream->vrev = oggstream->header[0][9]; |
| 367 av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n", | 385 av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n", |
| 368 oggstream->kfgshift, oggstream->vrev); | 386 oggstream->kfgshift, oggstream->vrev); |
| 369 } | 387 } |
| 370 } | 388 } |
| 371 } | 389 } |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 "application/ogg", | 490 "application/ogg", |
| 473 "ogg,ogv,spx", | 491 "ogg,ogv,spx", |
| 474 sizeof(OGGContext), | 492 sizeof(OGGContext), |
| 475 CODEC_ID_FLAC, | 493 CODEC_ID_FLAC, |
| 476 CODEC_ID_THEORA, | 494 CODEC_ID_THEORA, |
| 477 ogg_write_header, | 495 ogg_write_header, |
| 478 ogg_write_packet, | 496 ogg_write_packet, |
| 479 ogg_write_trailer, | 497 ogg_write_trailer, |
| 480 .metadata_conv = ff_vorbiscomment_metadata_conv, | 498 .metadata_conv = ff_vorbiscomment_metadata_conv, |
| 481 }; | 499 }; |
| OLD | NEW |