Libav 0.7.1
|
00001 /* 00002 * Ogg muxer 00003 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr> 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavutil/crc.h" 00023 #include "libavutil/random_seed.h" 00024 #include "libavcodec/xiph.h" 00025 #include "libavcodec/bytestream.h" 00026 #include "libavcodec/flac.h" 00027 #include "avformat.h" 00028 #include "avio_internal.h" 00029 #include "internal.h" 00030 #include "vorbiscomment.h" 00031 00032 #define MAX_PAGE_SIZE 65025 00033 00034 typedef struct { 00035 int64_t granule; 00036 int stream_index; 00037 uint8_t flags; 00038 uint8_t segments_count; 00039 uint8_t segments[255]; 00040 uint8_t data[MAX_PAGE_SIZE]; 00041 uint16_t size; 00042 } OGGPage; 00043 00044 typedef struct { 00045 unsigned page_counter; 00046 uint8_t *header[3]; 00047 int header_len[3]; 00049 int kfgshift; 00050 int64_t last_kf_pts; 00051 int vrev; 00052 int eos; 00053 unsigned page_count; 00054 OGGPage page; 00055 unsigned serial_num; 00056 int64_t last_granule; 00057 } OGGStreamContext; 00058 00059 typedef struct OGGPageList { 00060 OGGPage page; 00061 struct OGGPageList *next; 00062 } OGGPageList; 00063 00064 typedef struct { 00065 OGGPageList *page_list; 00066 } OGGContext; 00067 00068 static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset) 00069 { 00070 int64_t pos = avio_tell(pb); 00071 uint32_t checksum = ffio_get_checksum(pb); 00072 avio_seek(pb, crc_offset, SEEK_SET); 00073 avio_wb32(pb, checksum); 00074 avio_seek(pb, pos, SEEK_SET); 00075 } 00076 00077 static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags) 00078 { 00079 OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data; 00080 AVIOContext *pb; 00081 int64_t crc_offset; 00082 int ret, size; 00083 uint8_t *buf; 00084 00085 ret = avio_open_dyn_buf(&pb); 00086 if (ret < 0) 00087 return ret; 00088 ffio_init_checksum(pb, ff_crc04C11DB7_update, 0); 00089 ffio_wfourcc(pb, "OggS"); 00090 avio_w8(pb, 0); 00091 avio_w8(pb, page->flags | extra_flags); 00092 avio_wl64(pb, page->granule); 00093 avio_wl32(pb, oggstream->serial_num); 00094 avio_wl32(pb, oggstream->page_counter++); 00095 crc_offset = avio_tell(pb); 00096 avio_wl32(pb, 0); // crc 00097 avio_w8(pb, page->segments_count); 00098 avio_write(pb, page->segments, page->segments_count); 00099 avio_write(pb, page->data, page->size); 00100 00101 ogg_update_checksum(s, pb, crc_offset); 00102 avio_flush(pb); 00103 00104 size = avio_close_dyn_buf(pb, &buf); 00105 if (size < 0) 00106 return size; 00107 00108 avio_write(s->pb, buf, size); 00109 avio_flush(s->pb); 00110 av_free(buf); 00111 oggstream->page_count--; 00112 return 0; 00113 } 00114 00115 static int64_t ogg_granule_to_timestamp(OGGStreamContext *oggstream, int64_t granule) 00116 { 00117 if (oggstream->kfgshift) 00118 return (granule>>oggstream->kfgshift) + 00119 (granule & ((1<<oggstream->kfgshift)-1)); 00120 else 00121 return granule; 00122 } 00123 00124 static int ogg_compare_granule(AVFormatContext *s, OGGPage *next, OGGPage *page) 00125 { 00126 AVStream *st2 = s->streams[next->stream_index]; 00127 AVStream *st = s->streams[page->stream_index]; 00128 int64_t next_granule, cur_granule; 00129 00130 if (next->granule == -1 || page->granule == -1) 00131 return 0; 00132 00133 next_granule = av_rescale_q(ogg_granule_to_timestamp(st2->priv_data, next->granule), 00134 st2->time_base, AV_TIME_BASE_Q); 00135 cur_granule = av_rescale_q(ogg_granule_to_timestamp(st->priv_data, page->granule), 00136 st ->time_base, AV_TIME_BASE_Q); 00137 return next_granule > cur_granule; 00138 } 00139 00140 static int ogg_reset_cur_page(OGGStreamContext *oggstream) 00141 { 00142 oggstream->page.granule = -1; 00143 oggstream->page.flags = 0; 00144 oggstream->page.segments_count = 0; 00145 oggstream->page.size = 0; 00146 return 0; 00147 } 00148 00149 static int ogg_buffer_page(AVFormatContext *s, OGGStreamContext *oggstream) 00150 { 00151 OGGContext *ogg = s->priv_data; 00152 OGGPageList **p = &ogg->page_list; 00153 OGGPageList *l = av_mallocz(sizeof(*l)); 00154 00155 if (!l) 00156 return AVERROR(ENOMEM); 00157 l->page = oggstream->page; 00158 00159 oggstream->page_count++; 00160 ogg_reset_cur_page(oggstream); 00161 00162 while (*p) { 00163 if (ogg_compare_granule(s, &(*p)->page, &l->page)) 00164 break; 00165 p = &(*p)->next; 00166 } 00167 l->next = *p; 00168 *p = l; 00169 00170 return 0; 00171 } 00172 00173 static int ogg_buffer_data(AVFormatContext *s, AVStream *st, 00174 uint8_t *data, unsigned size, int64_t granule) 00175 { 00176 OGGStreamContext *oggstream = st->priv_data; 00177 int total_segments = size / 255 + 1; 00178 uint8_t *p = data; 00179 int i, segments, len, flush = 0; 00180 00181 // Handles VFR by flushing page because this frame needs to have a timestamp 00182 if (st->codec->codec_id == CODEC_ID_THEORA && 00183 ogg_granule_to_timestamp(oggstream, granule) > 00184 ogg_granule_to_timestamp(oggstream, oggstream->last_granule) + 1) { 00185 if (oggstream->page.granule != -1) 00186 ogg_buffer_page(s, oggstream); 00187 flush = 1; 00188 } 00189 00190 for (i = 0; i < total_segments; ) { 00191 OGGPage *page = &oggstream->page; 00192 00193 segments = FFMIN(total_segments - i, 255 - page->segments_count); 00194 00195 if (i && !page->segments_count) 00196 page->flags |= 1; // continued packet 00197 00198 memset(page->segments+page->segments_count, 255, segments - 1); 00199 page->segments_count += segments - 1; 00200 00201 len = FFMIN(size, segments*255); 00202 page->segments[page->segments_count++] = len - (segments-1)*255; 00203 memcpy(page->data+page->size, p, len); 00204 p += len; 00205 size -= len; 00206 i += segments; 00207 page->size += len; 00208 00209 if (i == total_segments) 00210 page->granule = granule; 00211 00212 if (page->segments_count == 255) { 00213 ogg_buffer_page(s, oggstream); 00214 } 00215 } 00216 00217 if (flush && oggstream->page.granule != -1) 00218 ogg_buffer_page(s, oggstream); 00219 00220 return 0; 00221 } 00222 00223 static uint8_t *ogg_write_vorbiscomment(int offset, int bitexact, 00224 int *header_len, AVDictionary **m, int framing_bit) 00225 { 00226 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT; 00227 int size; 00228 uint8_t *p, *p0; 00229 unsigned int count; 00230 00231 ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL); 00232 00233 size = offset + ff_vorbiscomment_length(*m, vendor, &count) + framing_bit; 00234 p = av_mallocz(size); 00235 if (!p) 00236 return NULL; 00237 p0 = p; 00238 00239 p += offset; 00240 ff_vorbiscomment_write(&p, m, vendor, count); 00241 if (framing_bit) 00242 bytestream_put_byte(&p, 1); 00243 00244 *header_len = size; 00245 return p0; 00246 } 00247 00248 static int ogg_build_flac_headers(AVCodecContext *avctx, 00249 OGGStreamContext *oggstream, int bitexact, 00250 AVDictionary **m) 00251 { 00252 enum FLACExtradataFormat format; 00253 uint8_t *streaminfo; 00254 uint8_t *p; 00255 00256 if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo)) 00257 return -1; 00258 00259 // first packet: STREAMINFO 00260 oggstream->header_len[0] = 51; 00261 oggstream->header[0] = av_mallocz(51); // per ogg flac specs 00262 p = oggstream->header[0]; 00263 if (!p) 00264 return AVERROR(ENOMEM); 00265 bytestream_put_byte(&p, 0x7F); 00266 bytestream_put_buffer(&p, "FLAC", 4); 00267 bytestream_put_byte(&p, 1); // major version 00268 bytestream_put_byte(&p, 0); // minor version 00269 bytestream_put_be16(&p, 1); // headers packets without this one 00270 bytestream_put_buffer(&p, "fLaC", 4); 00271 bytestream_put_byte(&p, 0x00); // streaminfo 00272 bytestream_put_be24(&p, 34); 00273 bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE); 00274 00275 // second packet: VorbisComment 00276 p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m, 0); 00277 if (!p) 00278 return AVERROR(ENOMEM); 00279 oggstream->header[1] = p; 00280 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment 00281 bytestream_put_be24(&p, oggstream->header_len[1] - 4); 00282 00283 return 0; 00284 } 00285 00286 #define SPEEX_HEADER_SIZE 80 00287 00288 static int ogg_build_speex_headers(AVCodecContext *avctx, 00289 OGGStreamContext *oggstream, int bitexact, 00290 AVDictionary **m) 00291 { 00292 uint8_t *p; 00293 00294 if (avctx->extradata_size < SPEEX_HEADER_SIZE) 00295 return -1; 00296 00297 // first packet: Speex header 00298 p = av_mallocz(SPEEX_HEADER_SIZE); 00299 if (!p) 00300 return AVERROR(ENOMEM); 00301 oggstream->header[0] = p; 00302 oggstream->header_len[0] = SPEEX_HEADER_SIZE; 00303 bytestream_put_buffer(&p, avctx->extradata, SPEEX_HEADER_SIZE); 00304 AV_WL32(&oggstream->header[0][68], 0); // set extra_headers to 0 00305 00306 // second packet: VorbisComment 00307 p = ogg_write_vorbiscomment(0, bitexact, &oggstream->header_len[1], m, 0); 00308 if (!p) 00309 return AVERROR(ENOMEM); 00310 oggstream->header[1] = p; 00311 00312 return 0; 00313 } 00314 00315 static int ogg_write_header(AVFormatContext *s) 00316 { 00317 OGGStreamContext *oggstream; 00318 int i, j; 00319 00320 for (i = 0; i < s->nb_streams; i++) { 00321 AVStream *st = s->streams[i]; 00322 unsigned serial_num = i; 00323 00324 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) 00325 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00326 else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) 00327 av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den); 00328 if (st->codec->codec_id != CODEC_ID_VORBIS && 00329 st->codec->codec_id != CODEC_ID_THEORA && 00330 st->codec->codec_id != CODEC_ID_SPEEX && 00331 st->codec->codec_id != CODEC_ID_FLAC) { 00332 av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i); 00333 return -1; 00334 } 00335 00336 if (!st->codec->extradata || !st->codec->extradata_size) { 00337 av_log(s, AV_LOG_ERROR, "No extradata present\n"); 00338 return -1; 00339 } 00340 oggstream = av_mallocz(sizeof(*oggstream)); 00341 oggstream->page.stream_index = i; 00342 00343 if (!(st->codec->flags & CODEC_FLAG_BITEXACT)) 00344 do { 00345 serial_num = av_get_random_seed(); 00346 for (j = 0; j < i; j++) { 00347 OGGStreamContext *sc = s->streams[j]->priv_data; 00348 if (serial_num == sc->serial_num) 00349 break; 00350 } 00351 } while (j < i); 00352 oggstream->serial_num = serial_num; 00353 00354 st->priv_data = oggstream; 00355 if (st->codec->codec_id == CODEC_ID_FLAC) { 00356 int err = ogg_build_flac_headers(st->codec, oggstream, 00357 st->codec->flags & CODEC_FLAG_BITEXACT, 00358 &s->metadata); 00359 if (err) { 00360 av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n"); 00361 av_freep(&st->priv_data); 00362 return err; 00363 } 00364 } else if (st->codec->codec_id == CODEC_ID_SPEEX) { 00365 int err = ogg_build_speex_headers(st->codec, oggstream, 00366 st->codec->flags & CODEC_FLAG_BITEXACT, 00367 &s->metadata); 00368 if (err) { 00369 av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); 00370 av_freep(&st->priv_data); 00371 return err; 00372 } 00373 } else { 00374 uint8_t *p; 00375 const char *cstr = st->codec->codec_id == CODEC_ID_VORBIS ? "vorbis" : "theora"; 00376 int header_type = st->codec->codec_id == CODEC_ID_VORBIS ? 3 : 0x81; 00377 int framing_bit = st->codec->codec_id == CODEC_ID_VORBIS ? 1 : 0; 00378 00379 if (ff_split_xiph_headers(st->codec->extradata, st->codec->extradata_size, 00380 st->codec->codec_id == CODEC_ID_VORBIS ? 30 : 42, 00381 oggstream->header, oggstream->header_len) < 0) { 00382 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n"); 00383 av_freep(&st->priv_data); 00384 return -1; 00385 } 00386 00387 p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT, 00388 &oggstream->header_len[1], &s->metadata, 00389 framing_bit); 00390 if (!p) 00391 return AVERROR(ENOMEM); 00392 00393 oggstream->header[1] = p; 00394 bytestream_put_byte(&p, header_type); 00395 bytestream_put_buffer(&p, cstr, 6); 00396 00397 if (st->codec->codec_id == CODEC_ID_THEORA) { 00400 oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5); 00401 oggstream->vrev = oggstream->header[0][9]; 00402 av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n", 00403 oggstream->kfgshift, oggstream->vrev); 00404 } 00405 } 00406 } 00407 00408 for (j = 0; j < s->nb_streams; j++) { 00409 OGGStreamContext *oggstream = s->streams[j]->priv_data; 00410 ogg_buffer_data(s, s->streams[j], oggstream->header[0], 00411 oggstream->header_len[0], 0); 00412 oggstream->page.flags |= 2; // bos 00413 ogg_buffer_page(s, oggstream); 00414 } 00415 for (j = 0; j < s->nb_streams; j++) { 00416 AVStream *st = s->streams[j]; 00417 OGGStreamContext *oggstream = st->priv_data; 00418 for (i = 1; i < 3; i++) { 00419 if (oggstream && oggstream->header_len[i]) 00420 ogg_buffer_data(s, st, oggstream->header[i], 00421 oggstream->header_len[i], 0); 00422 } 00423 ogg_buffer_page(s, oggstream); 00424 } 00425 return 0; 00426 } 00427 00428 static void ogg_write_pages(AVFormatContext *s, int flush) 00429 { 00430 OGGContext *ogg = s->priv_data; 00431 OGGPageList *next, *p; 00432 00433 if (!ogg->page_list) 00434 return; 00435 00436 for (p = ogg->page_list; p; ) { 00437 OGGStreamContext *oggstream = 00438 s->streams[p->page.stream_index]->priv_data; 00439 if (oggstream->page_count < 2 && !flush) 00440 break; 00441 ogg_write_page(s, &p->page, 00442 flush && oggstream->page_count == 1 ? 4 : 0); // eos 00443 next = p->next; 00444 av_freep(&p); 00445 p = next; 00446 } 00447 ogg->page_list = p; 00448 } 00449 00450 static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt) 00451 { 00452 AVStream *st = s->streams[pkt->stream_index]; 00453 OGGStreamContext *oggstream = st->priv_data; 00454 int ret; 00455 int64_t granule; 00456 00457 if (st->codec->codec_id == CODEC_ID_THEORA) { 00458 int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration; 00459 int pframe_count; 00460 if (pkt->flags & AV_PKT_FLAG_KEY) 00461 oggstream->last_kf_pts = pts; 00462 pframe_count = pts - oggstream->last_kf_pts; 00463 // prevent frame count from overflow if key frame flag is not set 00464 if (pframe_count >= (1<<oggstream->kfgshift)) { 00465 oggstream->last_kf_pts += pframe_count; 00466 pframe_count = 0; 00467 } 00468 granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count; 00469 } else 00470 granule = pkt->pts + pkt->duration; 00471 00472 ret = ogg_buffer_data(s, st, pkt->data, pkt->size, granule); 00473 if (ret < 0) 00474 return ret; 00475 00476 ogg_write_pages(s, 0); 00477 00478 oggstream->last_granule = granule; 00479 00480 return 0; 00481 } 00482 00483 static int ogg_write_trailer(AVFormatContext *s) 00484 { 00485 int i; 00486 00487 /* flush current page */ 00488 for (i = 0; i < s->nb_streams; i++) 00489 ogg_buffer_page(s, s->streams[i]->priv_data); 00490 00491 ogg_write_pages(s, 1); 00492 00493 for (i = 0; i < s->nb_streams; i++) { 00494 AVStream *st = s->streams[i]; 00495 OGGStreamContext *oggstream = st->priv_data; 00496 if (st->codec->codec_id == CODEC_ID_FLAC || 00497 st->codec->codec_id == CODEC_ID_SPEEX) { 00498 av_free(oggstream->header[0]); 00499 av_free(oggstream->header[1]); 00500 } 00501 av_freep(&st->priv_data); 00502 } 00503 return 0; 00504 } 00505 00506 AVOutputFormat ff_ogg_muxer = { 00507 "ogg", 00508 NULL_IF_CONFIG_SMALL("Ogg"), 00509 "application/ogg", 00510 "ogg,ogv,spx", 00511 sizeof(OGGContext), 00512 CODEC_ID_FLAC, 00513 CODEC_ID_THEORA, 00514 ogg_write_header, 00515 ogg_write_packet, 00516 ogg_write_trailer, 00517 };