Mercurial > libavformat.hg
annotate rmenc.c @ 6260:5c17c20dd67a libavformat
In ogg muxer, use dyn buffer to compute crc of the page, fix muxing with pipe
when page buffer is bigger than default buffer size. Max page is 65k.
author | bcoudurier |
---|---|
date | Wed, 14 Jul 2010 23:21:18 +0000 |
parents | 490c440a53e7 |
children |
rev | line source |
---|---|
0 | 1 /* |
2103 | 2 * "Real" compatible muxer. |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4097
diff
changeset
|
3 * Copyright (c) 2000, 2001 Fabrice Bellard |
0 | 4 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 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. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1350
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
888
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
21 #include "avformat.h" | |
2103 | 22 #include "rm.h" |
0 | 23 |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
24 typedef struct { |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
25 int nb_packets; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
26 int packet_total_size; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
27 int packet_max_size; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
28 /* codec related output */ |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
29 int bit_rate; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
30 float frame_rate; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
31 int nb_frames; /* current frame number */ |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
32 int total_frames; /* total number of frames */ |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
33 int num; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
34 AVCodecContext *enc; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
35 } StreamInfo; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
36 |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
37 typedef struct { |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
38 StreamInfo streams[2]; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
39 StreamInfo *audio_stream, *video_stream; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
40 int data_pos; /* position of the data after the header */ |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
41 } RMMuxContext; |
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
42 |
0 | 43 /* in ms */ |
885 | 44 #define BUFFER_DURATION 0 |
0 | 45 |
46 | |
47 static void put_str(ByteIOContext *s, const char *tag) | |
48 { | |
49 put_be16(s,strlen(tag)); | |
50 while (*tag) { | |
51 put_byte(s, *tag++); | |
52 } | |
53 } | |
54 | |
55 static void put_str8(ByteIOContext *s, const char *tag) | |
56 { | |
57 put_byte(s, strlen(tag)); | |
58 while (*tag) { | |
59 put_byte(s, *tag++); | |
60 } | |
61 } | |
62 | |
6065
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
63 static int rv10_write_header(AVFormatContext *ctx, |
6066 | 64 int data_size, int index_pos) |
0 | 65 { |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
66 RMMuxContext *rm = ctx->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
67 ByteIOContext *s = ctx->pb; |
0 | 68 StreamInfo *stream; |
69 unsigned char *data_offset_ptr, *start_ptr; | |
70 const char *desc, *mimetype; | |
71 int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i; | |
72 int bit_rate, v, duration, flags, data_pos; | |
4522 | 73 AVMetadataTag *tag; |
0 | 74 |
75 start_ptr = s->buf_ptr; | |
76 | |
77 put_tag(s, ".RMF"); | |
78 put_be32(s,18); /* header size */ | |
79 put_be16(s,0); | |
80 put_be32(s,0); | |
81 put_be32(s,4 + ctx->nb_streams); /* num headers */ | |
82 | |
83 put_tag(s,"PROP"); | |
84 put_be32(s, 50); | |
85 put_be16(s, 0); | |
86 packet_max_size = 0; | |
87 packet_total_size = 0; | |
88 nb_packets = 0; | |
89 bit_rate = 0; | |
90 duration = 0; | |
91 for(i=0;i<ctx->nb_streams;i++) { | |
92 StreamInfo *stream = &rm->streams[i]; | |
93 bit_rate += stream->bit_rate; | |
94 if (stream->packet_max_size > packet_max_size) | |
95 packet_max_size = stream->packet_max_size; | |
96 nb_packets += stream->nb_packets; | |
97 packet_total_size += stream->packet_total_size; | |
98 /* select maximum duration */ | |
99 v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate); | |
100 if (v > duration) | |
101 duration = v; | |
102 } | |
103 put_be32(s, bit_rate); /* max bit rate */ | |
104 put_be32(s, bit_rate); /* avg bit rate */ | |
105 put_be32(s, packet_max_size); /* max packet size */ | |
106 if (nb_packets > 0) | |
107 packet_avg_size = packet_total_size / nb_packets; | |
108 else | |
109 packet_avg_size = 0; | |
110 put_be32(s, packet_avg_size); /* avg packet size */ | |
111 put_be32(s, nb_packets); /* num packets */ | |
112 put_be32(s, duration); /* duration */ | |
113 put_be32(s, BUFFER_DURATION); /* preroll */ | |
114 put_be32(s, index_pos); /* index offset */ | |
115 /* computation of data the data offset */ | |
116 data_offset_ptr = s->buf_ptr; | |
117 put_be32(s, 0); /* data offset : will be patched after */ | |
118 put_be16(s, ctx->nb_streams); /* num streams */ | |
119 flags = 1 | 2; /* save allowed & perfect play */ | |
120 if (url_is_streamed(s)) | |
121 flags |= 4; /* live broadcast */ | |
122 put_be16(s, flags); | |
885 | 123 |
0 | 124 /* comments */ |
125 | |
126 put_tag(s,"CONT"); | |
4522 | 127 size = 4 * 2 + 10; |
128 for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { | |
129 tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); | |
130 if(tag) size += strlen(tag->value); | |
131 } | |
0 | 132 put_be32(s,size); |
133 put_be16(s,0); | |
4522 | 134 for(i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { |
135 tag = av_metadata_get(ctx->metadata, ff_rm_metadata[i], NULL, 0); | |
136 put_str(s, tag ? tag->value : ""); | |
137 } | |
885 | 138 |
0 | 139 for(i=0;i<ctx->nb_streams;i++) { |
140 int codec_data_size; | |
141 | |
142 stream = &rm->streams[i]; | |
885 | 143 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4770
diff
changeset
|
144 if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { |
0 | 145 desc = "The Audio Stream"; |
146 mimetype = "audio/x-pn-realaudio"; | |
147 codec_data_size = 73; | |
148 } else { | |
149 desc = "The Video Stream"; | |
150 mimetype = "video/x-pn-realvideo"; | |
151 codec_data_size = 34; | |
152 } | |
153 | |
154 put_tag(s,"MDPR"); | |
155 size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size; | |
156 put_be32(s, size); | |
157 put_be16(s, 0); | |
158 | |
159 put_be16(s, i); /* stream number */ | |
160 put_be32(s, stream->bit_rate); /* max bit rate */ | |
161 put_be32(s, stream->bit_rate); /* avg bit rate */ | |
162 put_be32(s, stream->packet_max_size); /* max packet size */ | |
163 if (stream->nb_packets > 0) | |
885 | 164 packet_avg_size = stream->packet_total_size / |
0 | 165 stream->nb_packets; |
166 else | |
167 packet_avg_size = 0; | |
168 put_be32(s, packet_avg_size); /* avg packet size */ | |
169 put_be32(s, 0); /* start time */ | |
170 put_be32(s, BUFFER_DURATION); /* preroll */ | |
171 /* duration */ | |
172 if (url_is_streamed(s) || !stream->total_frames) | |
173 put_be32(s, (int)(3600 * 1000)); | |
174 else | |
175 put_be32(s, (int)(stream->total_frames * 1000 / stream->frame_rate)); | |
176 put_str8(s, desc); | |
177 put_str8(s, mimetype); | |
178 put_be32(s, codec_data_size); | |
885 | 179 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4770
diff
changeset
|
180 if (stream->enc->codec_type == AVMEDIA_TYPE_AUDIO) { |
0 | 181 int coded_frame_size, fscode, sample_rate; |
182 sample_rate = stream->enc->sample_rate; | |
885 | 183 coded_frame_size = (stream->enc->bit_rate * |
0 | 184 stream->enc->frame_size) / (8 * sample_rate); |
185 /* audio codec info */ | |
186 put_tag(s, ".ra"); | |
187 put_byte(s, 0xfd); | |
188 put_be32(s, 0x00040000); /* version */ | |
189 put_tag(s, ".ra4"); | |
190 put_be32(s, 0x01b53530); /* stream length */ | |
191 put_be16(s, 4); /* unknown */ | |
192 put_be32(s, 0x39); /* header size */ | |
193 | |
194 switch(sample_rate) { | |
195 case 48000: | |
196 case 24000: | |
197 case 12000: | |
198 fscode = 1; | |
199 break; | |
200 default: | |
201 case 44100: | |
202 case 22050: | |
203 case 11025: | |
204 fscode = 2; | |
205 break; | |
206 case 32000: | |
207 case 16000: | |
208 case 8000: | |
209 fscode = 3; | |
210 } | |
3624
8b4be8aa2324
cosmetics: make all references to AC-3 capitalized and hyphenated
jbr
parents:
3424
diff
changeset
|
211 put_be16(s, fscode); /* codec additional info, for AC-3, seems |
0 | 212 to be a frequency code */ |
213 /* special hack to compensate rounding errors... */ | |
214 if (coded_frame_size == 557) | |
215 coded_frame_size--; | |
216 put_be32(s, coded_frame_size); /* frame length */ | |
217 put_be32(s, 0x51540); /* unknown */ | |
218 put_be32(s, 0x249f0); /* unknown */ | |
219 put_be32(s, 0x249f0); /* unknown */ | |
220 put_be16(s, 0x01); | |
221 /* frame length : seems to be very important */ | |
885 | 222 put_be16(s, coded_frame_size); |
0 | 223 put_be32(s, 0); /* unknown */ |
224 put_be16(s, stream->enc->sample_rate); /* sample rate */ | |
225 put_be32(s, 0x10); /* unknown */ | |
226 put_be16(s, stream->enc->channels); | |
227 put_str8(s, "Int0"); /* codec name */ | |
6065
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
228 if (stream->enc->codec_tag) { |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
229 put_byte(s, 4); /* tag length */ |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
230 put_le32(s, stream->enc->codec_tag); |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
231 } else { |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
232 av_log(ctx, AV_LOG_ERROR, "Invalid codec tag\n"); |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
233 return -1; |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
234 } |
0 | 235 put_be16(s, 0); /* title length */ |
236 put_be16(s, 0); /* author length */ | |
237 put_be16(s, 0); /* copyright length */ | |
238 put_byte(s, 0); /* end of header */ | |
239 } else { | |
240 /* video codec info */ | |
241 put_be32(s,34); /* size */ | |
614 | 242 if(stream->enc->codec_id == CODEC_ID_RV10) |
243 put_tag(s,"VIDORV10"); | |
244 else | |
245 put_tag(s,"VIDORV20"); | |
0 | 246 put_be16(s, stream->enc->width); |
247 put_be16(s, stream->enc->height); | |
248 put_be16(s, (int) stream->frame_rate); /* frames per seconds ? */ | |
249 put_be32(s,0); /* unknown meaning */ | |
250 put_be16(s, (int) stream->frame_rate); /* unknown meaning */ | |
251 put_be32(s,0); /* unknown meaning */ | |
252 put_be16(s, 8); /* unknown meaning */ | |
253 /* Seems to be the codec version: only use basic H263. The next | |
254 versions seems to add a diffential DC coding as in | |
255 MPEG... nothing new under the sun */ | |
614 | 256 if(stream->enc->codec_id == CODEC_ID_RV10) |
885 | 257 put_be32(s,0x10000000); |
614 | 258 else |
885 | 259 put_be32(s,0x20103001); |
260 //put_be32(s,0x10003000); | |
0 | 261 } |
262 } | |
263 | |
264 /* patch data offset field */ | |
265 data_pos = s->buf_ptr - start_ptr; | |
266 rm->data_pos = data_pos; | |
267 data_offset_ptr[0] = data_pos >> 24; | |
268 data_offset_ptr[1] = data_pos >> 16; | |
269 data_offset_ptr[2] = data_pos >> 8; | |
270 data_offset_ptr[3] = data_pos; | |
885 | 271 |
0 | 272 /* data stream */ |
273 put_tag(s,"DATA"); | |
274 put_be32(s,data_size + 10 + 8); | |
275 put_be16(s,0); | |
276 | |
277 put_be32(s, nb_packets); /* number of packets */ | |
278 put_be32(s,0); /* next data header */ | |
6065
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
279 return 0; |
0 | 280 } |
281 | |
885 | 282 static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream, |
0 | 283 int length, int key_frame) |
284 { | |
285 int timestamp; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
286 ByteIOContext *s = ctx->pb; |
0 | 287 |
288 stream->nb_packets++; | |
289 stream->packet_total_size += length; | |
290 if (length > stream->packet_max_size) | |
291 stream->packet_max_size = length; | |
292 | |
293 put_be16(s,0); /* version */ | |
294 put_be16(s,length + 12); | |
295 put_be16(s, stream->num); /* stream number */ | |
296 timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate; | |
297 put_be32(s, timestamp); /* timestamp */ | |
298 put_byte(s, 0); /* reserved */ | |
299 put_byte(s, key_frame ? 2 : 0); /* flags */ | |
300 } | |
301 | |
302 static int rm_write_header(AVFormatContext *s) | |
303 { | |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
304 RMMuxContext *rm = s->priv_data; |
0 | 305 StreamInfo *stream; |
306 int n; | |
307 AVCodecContext *codec; | |
308 | |
309 for(n=0;n<s->nb_streams;n++) { | |
310 s->streams[n]->id = n; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
311 codec = s->streams[n]->codec; |
0 | 312 stream = &rm->streams[n]; |
313 memset(stream, 0, sizeof(StreamInfo)); | |
314 stream->num = n; | |
315 stream->bit_rate = codec->bit_rate; | |
316 stream->enc = codec; | |
317 | |
318 switch(codec->codec_type) { | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4770
diff
changeset
|
319 case AVMEDIA_TYPE_AUDIO: |
0 | 320 rm->audio_stream = stream; |
321 stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size; | |
322 /* XXX: dummy values */ | |
323 stream->packet_max_size = 1024; | |
324 stream->nb_packets = 0; | |
325 stream->total_frames = stream->nb_packets; | |
326 break; | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4770
diff
changeset
|
327 case AVMEDIA_TYPE_VIDEO: |
0 | 328 rm->video_stream = stream; |
743 | 329 stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num; |
0 | 330 /* XXX: dummy values */ |
331 stream->packet_max_size = 4096; | |
332 stream->nb_packets = 0; | |
333 stream->total_frames = stream->nb_packets; | |
334 break; | |
335 default: | |
537 | 336 return -1; |
0 | 337 } |
338 } | |
339 | |
6065
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
340 if (rv10_write_header(s, 0, 0)) |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
341 return AVERROR_INVALIDDATA; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
342 put_flush_packet(s->pb); |
0 | 343 return 0; |
344 } | |
345 | |
470 | 346 static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags) |
0 | 347 { |
65 | 348 uint8_t *buf1; |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
349 RMMuxContext *rm = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
350 ByteIOContext *pb = s->pb; |
0 | 351 StreamInfo *stream = rm->audio_stream; |
352 int i; | |
353 | |
354 /* XXX: suppress this malloc */ | |
65 | 355 buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) ); |
885 | 356 |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
357 write_packet_header(s, stream, size, !!(flags & AV_PKT_FLAG_KEY)); |
885 | 358 |
6065
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
359 if (stream->enc->codec_id == CODEC_ID_AC3) { |
6066 | 360 /* for AC-3, the words seem to be reversed */ |
361 for(i=0;i<size;i+=2) { | |
362 buf1[i] = buf[i+1]; | |
363 buf1[i+1] = buf[i]; | |
364 } | |
365 put_buffer(pb, buf1, size); | |
6065
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
366 } else { |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
367 put_buffer(pb, buf, size); |
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
368 } |
0 | 369 put_flush_packet(pb); |
370 stream->nb_frames++; | |
371 av_free(buf1); | |
372 return 0; | |
373 } | |
374 | |
470 | 375 static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags) |
0 | 376 { |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
377 RMMuxContext *rm = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
378 ByteIOContext *pb = s->pb; |
0 | 379 StreamInfo *stream = rm->video_stream; |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
380 int key_frame = !!(flags & AV_PKT_FLAG_KEY); |
0 | 381 |
382 /* XXX: this is incorrect: should be a parameter */ | |
383 | |
384 /* Well, I spent some time finding the meaning of these bits. I am | |
385 not sure I understood everything, but it works !! */ | |
386 #if 1 | |
2792
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
387 write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame); |
0 | 388 /* bit 7: '1' if final packet of a frame converted in several packets */ |
885 | 389 put_byte(pb, 0x81); |
0 | 390 /* bit 7: '1' if I frame. bits 6..0 : sequence number in current |
391 frame starting from 1 */ | |
392 if (key_frame) { | |
885 | 393 put_byte(pb, 0x81); |
0 | 394 } else { |
885 | 395 put_byte(pb, 0x01); |
0 | 396 } |
2792
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
397 if(size >= 0x4000){ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
398 put_be32(pb, size); /* total frame size */ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
399 put_be32(pb, size); /* offset from the start or the end */ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
400 }else{ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
401 put_be16(pb, 0x4000 | size); /* total frame size */ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
402 put_be16(pb, 0x4000 | size); /* offset from the start or the end */ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
403 } |
0 | 404 #else |
405 /* full frame */ | |
406 write_packet_header(s, size + 6); | |
885 | 407 put_byte(pb, 0xc0); |
611 | 408 put_be16(pb, 0x4000 + size); /* total frame size */ |
0 | 409 put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */ |
410 #endif | |
885 | 411 put_byte(pb, stream->nb_frames & 0xff); |
412 | |
0 | 413 put_buffer(pb, buf, size); |
414 put_flush_packet(pb); | |
415 | |
416 stream->nb_frames++; | |
417 return 0; | |
418 } | |
419 | |
468 | 420 static int rm_write_packet(AVFormatContext *s, AVPacket *pkt) |
0 | 421 { |
885 | 422 if (s->streams[pkt->stream_index]->codec->codec_type == |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4770
diff
changeset
|
423 AVMEDIA_TYPE_AUDIO) |
470 | 424 return rm_write_audio(s, pkt->data, pkt->size, pkt->flags); |
0 | 425 else |
470 | 426 return rm_write_video(s, pkt->data, pkt->size, pkt->flags); |
0 | 427 } |
885 | 428 |
0 | 429 static int rm_write_trailer(AVFormatContext *s) |
430 { | |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
431 RMMuxContext *rm = s->priv_data; |
0 | 432 int data_size, index_pos, i; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
433 ByteIOContext *pb = s->pb; |
0 | 434 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
435 if (!url_is_streamed(s->pb)) { |
0 | 436 /* end of file: finish to write header */ |
437 index_pos = url_fseek(pb, 0, SEEK_CUR); | |
438 data_size = index_pos - rm->data_pos; | |
439 | |
4770
7875964b4a58
Remove index writing in RM muxer, since it is broken (multiple streams per
rbultje
parents:
4522
diff
changeset
|
440 /* FIXME: write index */ |
885 | 441 |
0 | 442 /* undocumented end header */ |
443 put_be32(pb, 0); | |
444 put_be32(pb, 0); | |
885 | 445 |
0 | 446 url_fseek(pb, 0, SEEK_SET); |
447 for(i=0;i<s->nb_streams;i++) | |
448 rm->streams[i].total_frames = rm->streams[i].nb_frames; | |
4770
7875964b4a58
Remove index writing in RM muxer, since it is broken (multiple streams per
rbultje
parents:
4522
diff
changeset
|
449 rv10_write_header(s, data_size, 0); |
0 | 450 } else { |
451 /* undocumented end header */ | |
452 put_be32(pb, 0); | |
453 put_be32(pb, 0); | |
454 } | |
455 put_flush_packet(pb); | |
456 return 0; | |
457 } | |
613 | 458 |
885 | 459 |
1169 | 460 AVOutputFormat rm_muxer = { |
0 | 461 "rm", |
4465 | 462 NULL_IF_CONFIG_SMALL("RealMedia format"), |
14
b167760cd0aa
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
michaelni
parents:
7
diff
changeset
|
463 "application/vnd.rn-realmedia", |
0 | 464 "rm,ra", |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
465 sizeof(RMMuxContext), |
0 | 466 CODEC_ID_AC3, |
467 CODEC_ID_RV10, | |
468 rm_write_header, | |
469 rm_write_packet, | |
470 rm_write_trailer, | |
6065
441608273a5c
Use ff_rm_codec_tags[] in RM muxer. This, incidentally, also allows muxing
rbultje
parents:
5913
diff
changeset
|
471 .codec_tag= (const AVCodecTag* const []){ff_rm_codec_tags, 0}, |
0 | 472 }; |