annotate oggenc.c @ 4037:5f65cbe25494 libavformat

Fix memleak caused by the fact that url_open_buf() allocates a context when calling, but url_close_buf() doesn't free it. The better solution is to not allocate it at all, init it with init_put_byte() and then not have to close it at all. In the case where we do need to hold it around for longer than within the function context, we allocate it with av_alloc_put_byte() and free it with av_free() instead. Discussed in ML thread "[PATCH] fix small memleak in rdt.c".
author rbultje
date Mon, 17 Nov 2008 14:23:20 +0000
parents 549a09cf23fe
children 92117125e17c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
1 /*
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
2 * Ogg muxer
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
3 * Copyright (c) 2007 Baptiste Coudurier <baptiste dot coudurier at free dot fr>
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
4 *
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
5 * This file is part of FFmpeg.
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
6 *
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
11 *
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
15 * Lesser General Public License for more details.
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
16 *
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
20 */
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
21
3286
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 3188
diff changeset
22 #include "libavutil/crc.h"
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 3188
diff changeset
23 #include "libavcodec/xiph.h"
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 3188
diff changeset
24 #include "libavcodec/bytestream.h"
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
25 #include "avformat.h"
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
26
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
27 typedef struct {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
28 int64_t duration;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
29 unsigned page_counter;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
30 uint8_t *header[3];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
31 int header_len[3];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
32 /** for theora granule */
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
33 int kfgshift;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
34 int64_t last_kf_pts;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
35 int vrev;
3021
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
36 int eos;
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
37 } OGGStreamContext;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
38
3973
549a09cf23fe Remove offset_t typedef and use int64_t directly instead.
diego
parents: 3593
diff changeset
39 static void ogg_update_checksum(AVFormatContext *s, int64_t crc_offset)
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
40 {
3973
549a09cf23fe Remove offset_t typedef and use int64_t directly instead.
diego
parents: 3593
diff changeset
41 int64_t pos = url_ftell(s->pb);
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
42 uint32_t checksum = get_checksum(s->pb);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
43 url_fseek(s->pb, crc_offset, SEEK_SET);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
44 put_be32(s->pb, checksum);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
45 url_fseek(s->pb, pos, SEEK_SET);
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
46 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
47
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
48 static int ogg_write_page(AVFormatContext *s, const uint8_t *data, int size,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
49 int64_t granule, int stream_index, int flags)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
50 {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
51 OGGStreamContext *oggstream = s->streams[stream_index]->priv_data;
3973
549a09cf23fe Remove offset_t typedef and use int64_t directly instead.
diego
parents: 3593
diff changeset
52 int64_t crc_offset;
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
53 int page_segments, i;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
54
3020
38777f77320e it seems ogg requires granule to be -1 on unfinished packets
bcoudurier
parents: 2771
diff changeset
55 if (size >= 255*255) {
38777f77320e it seems ogg requires granule to be -1 on unfinished packets
bcoudurier
parents: 2771
diff changeset
56 granule = -1;
38777f77320e it seems ogg requires granule to be -1 on unfinished packets
bcoudurier
parents: 2771
diff changeset
57 size = 255*255;
3021
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
58 } else if (oggstream->eos)
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
59 flags |= 4;
3020
38777f77320e it seems ogg requires granule to be -1 on unfinished packets
bcoudurier
parents: 2771
diff changeset
60
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
61 page_segments = FFMIN((size/255)+!!size, 255);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
62
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
63 init_checksum(s->pb, ff_crc04C11DB7_update, 0);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
64 put_tag(s->pb, "OggS");
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
65 put_byte(s->pb, 0);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
66 put_byte(s->pb, flags);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
67 put_le64(s->pb, granule);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
68 put_le32(s->pb, stream_index);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
69 put_le32(s->pb, oggstream->page_counter++);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
70 crc_offset = url_ftell(s->pb);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
71 put_le32(s->pb, 0); // crc
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
72 put_byte(s->pb, page_segments);
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
73 for (i = 0; i < page_segments-1; i++)
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
74 put_byte(s->pb, 255);
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
75 if (size) {
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
76 put_byte(s->pb, size - (page_segments-1)*255);
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
77 put_buffer(s->pb, data, size);
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
78 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
79 ogg_update_checksum(s, crc_offset);
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2731
diff changeset
80 put_flush_packet(s->pb);
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
81 return size;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
82 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
83
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
84 static int ogg_build_flac_headers(const uint8_t *extradata, int extradata_size,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
85 OGGStreamContext *oggstream, int bitexact)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
86 {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
87 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
88 uint8_t *p;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
89 if (extradata_size != 34)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
90 return -1;
3188
87119f0c4736 fix Ogg/FLAC header size
jbr
parents: 3021
diff changeset
91 oggstream->header_len[0] = 51;
87119f0c4736 fix Ogg/FLAC header size
jbr
parents: 3021
diff changeset
92 oggstream->header[0] = av_mallocz(51); // per ogg flac specs
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
93 p = oggstream->header[0];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
94 bytestream_put_byte(&p, 0x7F);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
95 bytestream_put_buffer(&p, "FLAC", 4);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
96 bytestream_put_byte(&p, 1); // major version
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
97 bytestream_put_byte(&p, 0); // minor version
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
98 bytestream_put_be16(&p, 1); // headers packets without this one
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
99 bytestream_put_buffer(&p, "fLaC", 4);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
100 bytestream_put_byte(&p, 0x00); // streaminfo
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
101 bytestream_put_be24(&p, 34);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
102 bytestream_put_buffer(&p, extradata, 34);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
103 oggstream->header_len[1] = 1+3+4+strlen(vendor)+4;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
104 oggstream->header[1] = av_mallocz(oggstream->header_len[1]);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
105 p = oggstream->header[1];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
106 bytestream_put_byte(&p, 0x84); // last metadata block and vorbis comment
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
107 bytestream_put_be24(&p, oggstream->header_len[1] - 4);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
108 bytestream_put_le32(&p, strlen(vendor));
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
109 bytestream_put_buffer(&p, vendor, strlen(vendor));
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
110 bytestream_put_le32(&p, 0); // user comment list length
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
111 return 0;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
112 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
113
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
114 static int ogg_write_header(AVFormatContext *s)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
115 {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
116 OGGStreamContext *oggstream;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
117 int i, j;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
118 for (i = 0; i < s->nb_streams; i++) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
119 AVStream *st = s->streams[i];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
120 if (st->codec->codec_type == CODEC_TYPE_AUDIO)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
121 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
122 else if (st->codec->codec_type == CODEC_TYPE_VIDEO)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
123 av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
124 if (st->codec->codec_id != CODEC_ID_VORBIS &&
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
125 st->codec->codec_id != CODEC_ID_THEORA &&
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
126 st->codec->codec_id != CODEC_ID_FLAC) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
127 av_log(s, AV_LOG_ERROR, "Unsupported codec id in stream %d\n", i);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
128 return -1;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
129 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
130
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
131 if (!st->codec->extradata || !st->codec->extradata_size) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
132 av_log(s, AV_LOG_ERROR, "No extradata present\n");
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
133 return -1;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
134 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
135 oggstream = av_mallocz(sizeof(*oggstream));
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
136 st->priv_data = oggstream;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
137 if (st->codec->codec_id == CODEC_ID_FLAC) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
138 if (ogg_build_flac_headers(st->codec->extradata, st->codec->extradata_size,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
139 oggstream, st->codec->flags & CODEC_FLAG_BITEXACT) < 0) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
140 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
141 av_freep(&st->priv_data);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
142 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
143 } else {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
144 if (ff_split_xiph_headers(st->codec->extradata, st->codec->extradata_size,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
145 st->codec->codec_id == CODEC_ID_VORBIS ? 30 : 42,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
146 oggstream->header, oggstream->header_len) < 0) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
147 av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
148 av_freep(&st->priv_data);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
149 return -1;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
150 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
151 if (st->codec->codec_id == CODEC_ID_THEORA) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
152 /** KFGSHIFT is the width of the less significant section of the granule position
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
153 The less significant section is the frame count since the last keyframe */
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
154 oggstream->kfgshift = ((oggstream->header[0][40]&3)<<3)|(oggstream->header[0][41]>>5);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
155 oggstream->vrev = oggstream->header[0][9];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
156 av_log(s, AV_LOG_DEBUG, "theora kfgshift %d, vrev %d\n",
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
157 oggstream->kfgshift, oggstream->vrev);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
158 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
159 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
160 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
161 for (i = 0; i < 3; i++) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
162 for (j = 0; j < s->nb_streams; j++) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
163 AVStream *st = s->streams[j];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
164 OGGStreamContext *oggstream = st->priv_data;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
165 if (oggstream && oggstream->header_len[i]) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
166 ogg_write_page(s, oggstream->header[i], oggstream->header_len[i],
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
167 0, st->index, i ? 0 : 2); // bos
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
168 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
169 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
170 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
171 return 0;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
172 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
173
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
174 static int ogg_write_packet(AVFormatContext *s, AVPacket *pkt)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
175 {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
176 AVStream *st = s->streams[pkt->stream_index];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
177 OGGStreamContext *oggstream = st->priv_data;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
178 uint8_t *ptr = pkt->data;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
179 int ret, size = pkt->size;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
180 int64_t granule;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
181
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
182 if (st->codec->codec_id == CODEC_ID_THEORA) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
183 int64_t pts = oggstream->vrev < 1 ? pkt->pts : pkt->pts + pkt->duration;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
184 int pframe_count;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
185 if (pkt->flags & PKT_FLAG_KEY)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
186 oggstream->last_kf_pts = pts;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
187 pframe_count = pts - oggstream->last_kf_pts;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
188 // prevent frame count from overflow if key frame flag is not set
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
189 if (pframe_count >= (1<<oggstream->kfgshift)) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
190 oggstream->last_kf_pts += pframe_count;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
191 pframe_count = 0;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
192 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
193 granule = (oggstream->last_kf_pts<<oggstream->kfgshift) | pframe_count;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
194 } else
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
195 granule = pkt->pts + pkt->duration;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
196 oggstream->duration = granule;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
197 do {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
198 ret = ogg_write_page(s, ptr, size, granule, pkt->stream_index, ptr != pkt->data);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
199 ptr += ret; size -= ret;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
200 } while (size > 0 || ret == 255*255); // need to output a last nil page
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
201
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
202 return 0;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
203 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
204
3021
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
205 int ogg_interleave_per_granule(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
206 {
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
207 AVPacketList *pktl, **next_point, *this_pktl;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
208 int stream_count = 0;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
209 int streams[MAX_STREAMS] = {0};
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
210 int interleaved = 0;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
211
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
212 if (pkt) {
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
213 AVStream *st = s->streams[pkt->stream_index];
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
214 this_pktl = av_mallocz(sizeof(AVPacketList));
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
215 this_pktl->pkt = *pkt;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
216 if (pkt->destruct == av_destruct_packet)
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
217 pkt->destruct = NULL; // not shared -> must keep original from being freed
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
218 else
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
219 av_dup_packet(&this_pktl->pkt); // shared -> must dup
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
220 next_point = &s->packet_buffer;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
221 while (*next_point) {
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
222 AVStream *st2 = s->streams[(*next_point)->pkt.stream_index];
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
223 AVPacket *next_pkt = &(*next_point)->pkt;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
224 int64_t cur_granule, next_granule;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
225 next_granule = av_rescale_q(next_pkt->pts + next_pkt->duration,
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
226 st2->time_base, AV_TIME_BASE_Q);
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
227 cur_granule = av_rescale_q(pkt->pts + pkt->duration,
3592
76964dfba31c cosmetics, remove space
bcoudurier
parents: 3424
diff changeset
228 st->time_base, AV_TIME_BASE_Q);
3021
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
229 if (next_granule > cur_granule)
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
230 break;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
231 next_point= &(*next_point)->next;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
232 }
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
233 this_pktl->next= *next_point;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
234 *next_point= this_pktl;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
235 }
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
236
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
237 pktl = s->packet_buffer;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
238 while (pktl) {
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
239 if (streams[pktl->pkt.stream_index] == 0)
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
240 stream_count++;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
241 streams[pktl->pkt.stream_index]++;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
242 // need to buffer at least one packet to set eos flag
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
243 if (streams[pktl->pkt.stream_index] == 2)
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
244 interleaved++;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
245 pktl = pktl->next;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
246 }
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
247
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
248 if ((s->nb_streams == stream_count && interleaved == stream_count) ||
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
249 (flush && stream_count)) {
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
250 pktl= s->packet_buffer;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
251 *out= pktl->pkt;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
252 s->packet_buffer = pktl->next;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
253 if (flush && streams[out->stream_index] == 1) {
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
254 OGGStreamContext *ogg = s->streams[out->stream_index]->priv_data;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
255 ogg->eos = 1;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
256 }
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
257 av_freep(&pktl);
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
258 return 1;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
259 } else {
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
260 av_init_packet(out);
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
261 return 0;
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
262 }
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
263 }
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
264
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
265 static int ogg_write_trailer(AVFormatContext *s)
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
266 {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
267 int i;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
268 for (i = 0; i < s->nb_streams; i++) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
269 AVStream *st = s->streams[i];
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
270 OGGStreamContext *oggstream = st->priv_data;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
271 if (st->codec->codec_id == CODEC_ID_FLAC) {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
272 av_free(oggstream->header[0]);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
273 av_free(oggstream->header[1]);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
274 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
275 av_freep(&st->priv_data);
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
276 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
277 return 0;
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
278 }
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
279
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
280 AVOutputFormat ogg_muxer = {
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
281 "ogg",
3424
7a0230981402 Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents: 3286
diff changeset
282 NULL_IF_CONFIG_SMALL("Ogg"),
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
283 "application/ogg",
3593
e08ec1936ad7 add ogv extension
bcoudurier
parents: 3592
diff changeset
284 "ogg,ogv",
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
285 0,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
286 CODEC_ID_FLAC,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
287 CODEC_ID_THEORA,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
288 ogg_write_header,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
289 ogg_write_packet,
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
290 ogg_write_trailer,
3021
6f393e79e896 Fix issue 338:
bcoudurier
parents: 3020
diff changeset
291 .interleave_packet = ogg_interleave_per_granule,
2731
6b43751d7264 ogg muxer
bcoudurier
parents:
diff changeset
292 };