Mercurial > libavformat.hg
annotate rmenc.c @ 5786:7d670040187e libavformat
In mpegts muxer, search for h264 aud nal, it might not be the first nal.
Improve ther error message when bitstream is malformated and tell user to use
the bitstream filter.
author | bcoudurier |
---|---|
date | Mon, 08 Mar 2010 23:59:05 +0000 |
parents | 7875964b4a58 |
children | 536e5527c1e0 |
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 | |
885 | 63 static void rv10_write_header(AVFormatContext *ctx, |
0 | 64 int data_size, int index_pos) |
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 |
0 | 144 if (stream->enc->codec_type == CODEC_TYPE_AUDIO) { |
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 |
0 | 180 if (stream->enc->codec_type == CODEC_TYPE_AUDIO) { |
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 */ | |
228 put_str8(s, "dnet"); /* codec name */ | |
229 put_be16(s, 0); /* title length */ | |
230 put_be16(s, 0); /* author length */ | |
231 put_be16(s, 0); /* copyright length */ | |
232 put_byte(s, 0); /* end of header */ | |
233 } else { | |
234 /* video codec info */ | |
235 put_be32(s,34); /* size */ | |
614 | 236 if(stream->enc->codec_id == CODEC_ID_RV10) |
237 put_tag(s,"VIDORV10"); | |
238 else | |
239 put_tag(s,"VIDORV20"); | |
0 | 240 put_be16(s, stream->enc->width); |
241 put_be16(s, stream->enc->height); | |
242 put_be16(s, (int) stream->frame_rate); /* frames per seconds ? */ | |
243 put_be32(s,0); /* unknown meaning */ | |
244 put_be16(s, (int) stream->frame_rate); /* unknown meaning */ | |
245 put_be32(s,0); /* unknown meaning */ | |
246 put_be16(s, 8); /* unknown meaning */ | |
247 /* Seems to be the codec version: only use basic H263. The next | |
248 versions seems to add a diffential DC coding as in | |
249 MPEG... nothing new under the sun */ | |
614 | 250 if(stream->enc->codec_id == CODEC_ID_RV10) |
885 | 251 put_be32(s,0x10000000); |
614 | 252 else |
885 | 253 put_be32(s,0x20103001); |
254 //put_be32(s,0x10003000); | |
0 | 255 } |
256 } | |
257 | |
258 /* patch data offset field */ | |
259 data_pos = s->buf_ptr - start_ptr; | |
260 rm->data_pos = data_pos; | |
261 data_offset_ptr[0] = data_pos >> 24; | |
262 data_offset_ptr[1] = data_pos >> 16; | |
263 data_offset_ptr[2] = data_pos >> 8; | |
264 data_offset_ptr[3] = data_pos; | |
885 | 265 |
0 | 266 /* data stream */ |
267 put_tag(s,"DATA"); | |
268 put_be32(s,data_size + 10 + 8); | |
269 put_be16(s,0); | |
270 | |
271 put_be32(s, nb_packets); /* number of packets */ | |
272 put_be32(s,0); /* next data header */ | |
273 } | |
274 | |
885 | 275 static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream, |
0 | 276 int length, int key_frame) |
277 { | |
278 int timestamp; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
279 ByteIOContext *s = ctx->pb; |
0 | 280 |
281 stream->nb_packets++; | |
282 stream->packet_total_size += length; | |
283 if (length > stream->packet_max_size) | |
284 stream->packet_max_size = length; | |
285 | |
286 put_be16(s,0); /* version */ | |
287 put_be16(s,length + 12); | |
288 put_be16(s, stream->num); /* stream number */ | |
289 timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate; | |
290 put_be32(s, timestamp); /* timestamp */ | |
291 put_byte(s, 0); /* reserved */ | |
292 put_byte(s, key_frame ? 2 : 0); /* flags */ | |
293 } | |
294 | |
295 static int rm_write_header(AVFormatContext *s) | |
296 { | |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
297 RMMuxContext *rm = s->priv_data; |
0 | 298 StreamInfo *stream; |
299 int n; | |
300 AVCodecContext *codec; | |
301 | |
302 for(n=0;n<s->nb_streams;n++) { | |
303 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
|
304 codec = s->streams[n]->codec; |
0 | 305 stream = &rm->streams[n]; |
306 memset(stream, 0, sizeof(StreamInfo)); | |
307 stream->num = n; | |
308 stream->bit_rate = codec->bit_rate; | |
309 stream->enc = codec; | |
310 | |
311 switch(codec->codec_type) { | |
312 case CODEC_TYPE_AUDIO: | |
313 rm->audio_stream = stream; | |
314 stream->frame_rate = (float)codec->sample_rate / (float)codec->frame_size; | |
315 /* XXX: dummy values */ | |
316 stream->packet_max_size = 1024; | |
317 stream->nb_packets = 0; | |
318 stream->total_frames = stream->nb_packets; | |
319 break; | |
320 case CODEC_TYPE_VIDEO: | |
321 rm->video_stream = stream; | |
743 | 322 stream->frame_rate = (float)codec->time_base.den / (float)codec->time_base.num; |
0 | 323 /* XXX: dummy values */ |
324 stream->packet_max_size = 4096; | |
325 stream->nb_packets = 0; | |
326 stream->total_frames = stream->nb_packets; | |
327 break; | |
328 default: | |
537 | 329 return -1; |
0 | 330 } |
331 } | |
332 | |
333 rv10_write_header(s, 0, 0); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
334 put_flush_packet(s->pb); |
0 | 335 return 0; |
336 } | |
337 | |
470 | 338 static int rm_write_audio(AVFormatContext *s, const uint8_t *buf, int size, int flags) |
0 | 339 { |
65 | 340 uint8_t *buf1; |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
341 RMMuxContext *rm = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
342 ByteIOContext *pb = s->pb; |
0 | 343 StreamInfo *stream = rm->audio_stream; |
344 int i; | |
345 | |
346 /* XXX: suppress this malloc */ | |
65 | 347 buf1= (uint8_t*) av_malloc( size * sizeof(uint8_t) ); |
885 | 348 |
470 | 349 write_packet_header(s, stream, size, !!(flags & PKT_FLAG_KEY)); |
885 | 350 |
3624
8b4be8aa2324
cosmetics: make all references to AC-3 capitalized and hyphenated
jbr
parents:
3424
diff
changeset
|
351 /* for AC-3, the words seem to be reversed */ |
0 | 352 for(i=0;i<size;i+=2) { |
353 buf1[i] = buf[i+1]; | |
354 buf1[i+1] = buf[i]; | |
355 } | |
356 put_buffer(pb, buf1, size); | |
357 put_flush_packet(pb); | |
358 stream->nb_frames++; | |
359 av_free(buf1); | |
360 return 0; | |
361 } | |
362 | |
470 | 363 static int rm_write_video(AVFormatContext *s, const uint8_t *buf, int size, int flags) |
0 | 364 { |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
365 RMMuxContext *rm = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
366 ByteIOContext *pb = s->pb; |
0 | 367 StreamInfo *stream = rm->video_stream; |
470 | 368 int key_frame = !!(flags & PKT_FLAG_KEY); |
0 | 369 |
370 /* XXX: this is incorrect: should be a parameter */ | |
371 | |
372 /* Well, I spent some time finding the meaning of these bits. I am | |
373 not sure I understood everything, but it works !! */ | |
374 #if 1 | |
2792
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
375 write_packet_header(s, stream, size + 7 + (size >= 0x4000)*4, key_frame); |
0 | 376 /* bit 7: '1' if final packet of a frame converted in several packets */ |
885 | 377 put_byte(pb, 0x81); |
0 | 378 /* bit 7: '1' if I frame. bits 6..0 : sequence number in current |
379 frame starting from 1 */ | |
380 if (key_frame) { | |
885 | 381 put_byte(pb, 0x81); |
0 | 382 } else { |
885 | 383 put_byte(pb, 0x01); |
0 | 384 } |
2792
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
385 if(size >= 0x4000){ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
386 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
|
387 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
|
388 }else{ |
e0a046abae56
Fix muxer so that generated files are playable by realplayer, other open
rtogni
parents:
2771
diff
changeset
|
389 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
|
390 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
|
391 } |
0 | 392 #else |
393 /* full frame */ | |
394 write_packet_header(s, size + 6); | |
885 | 395 put_byte(pb, 0xc0); |
611 | 396 put_be16(pb, 0x4000 + size); /* total frame size */ |
0 | 397 put_be16(pb, 0x4000 + packet_number * 126); /* position in stream */ |
398 #endif | |
885 | 399 put_byte(pb, stream->nb_frames & 0xff); |
400 | |
0 | 401 put_buffer(pb, buf, size); |
402 put_flush_packet(pb); | |
403 | |
404 stream->nb_frames++; | |
405 return 0; | |
406 } | |
407 | |
468 | 408 static int rm_write_packet(AVFormatContext *s, AVPacket *pkt) |
0 | 409 { |
885 | 410 if (s->streams[pkt->stream_index]->codec->codec_type == |
0 | 411 CODEC_TYPE_AUDIO) |
470 | 412 return rm_write_audio(s, pkt->data, pkt->size, pkt->flags); |
0 | 413 else |
470 | 414 return rm_write_video(s, pkt->data, pkt->size, pkt->flags); |
0 | 415 } |
885 | 416 |
0 | 417 static int rm_write_trailer(AVFormatContext *s) |
418 { | |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
419 RMMuxContext *rm = s->priv_data; |
0 | 420 int data_size, index_pos, i; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
421 ByteIOContext *pb = s->pb; |
0 | 422 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2103
diff
changeset
|
423 if (!url_is_streamed(s->pb)) { |
0 | 424 /* end of file: finish to write header */ |
425 index_pos = url_fseek(pb, 0, SEEK_CUR); | |
426 data_size = index_pos - rm->data_pos; | |
427 | |
4770
7875964b4a58
Remove index writing in RM muxer, since it is broken (multiple streams per
rbultje
parents:
4522
diff
changeset
|
428 /* FIXME: write index */ |
885 | 429 |
0 | 430 /* undocumented end header */ |
431 put_be32(pb, 0); | |
432 put_be32(pb, 0); | |
885 | 433 |
0 | 434 url_fseek(pb, 0, SEEK_SET); |
435 for(i=0;i<s->nb_streams;i++) | |
436 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
|
437 rv10_write_header(s, data_size, 0); |
0 | 438 } else { |
439 /* undocumented end header */ | |
440 put_be32(pb, 0); | |
441 put_be32(pb, 0); | |
442 } | |
443 put_flush_packet(pb); | |
444 return 0; | |
445 } | |
613 | 446 |
885 | 447 |
1169 | 448 AVOutputFormat rm_muxer = { |
0 | 449 "rm", |
4465 | 450 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
|
451 "application/vnd.rn-realmedia", |
0 | 452 "rm,ra", |
4097
f8a743bd2df8
Split RMContext into RMDemux/MuxContext and make them private in rmdec/enc.c.
rbultje
parents:
3624
diff
changeset
|
453 sizeof(RMMuxContext), |
0 | 454 CODEC_ID_AC3, |
455 CODEC_ID_RV10, | |
456 rm_write_header, | |
457 rm_write_packet, | |
458 rm_write_trailer, | |
459 }; |