Mercurial > libavformat.hg
annotate swf.c @ 3068:9cc9ff5aff9c libavformat
set bps to uncompressed original sound data for compressed audio
according to aiff specs, qt set it to 16 for mace and ima4,
fail if block align is not set.
author | bcoudurier |
---|---|
date | Mon, 25 Feb 2008 12:00:31 +0000 |
parents | 1b7bf70aab74 |
children | 6f61c3b36632 |
rev | line source |
---|---|
0 | 1 /* |
2 * Flash Compatible Streaming Format | |
3 * Copyright (c) 2000 Fabrice Bellard. | |
359 | 4 * Copyright (c) 2003 Tinic Uro. |
0 | 5 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
6 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
7 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
8 * FFmpeg is free software; you can redistribute it and/or |
0 | 9 * modify it under the terms of the GNU Lesser General Public |
10 * 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:
1305
diff
changeset
|
11 * version 2.1 of the License, or (at your option) any later version. |
0 | 12 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1305
diff
changeset
|
13 * FFmpeg is distributed in the hope that it will be useful, |
0 | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * 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:
1305
diff
changeset
|
19 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
887
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 21 */ |
22 #include "avformat.h" | |
628 | 23 #include "bitstream.h" |
1305 | 24 #include "riff.h" /* for CodecTag */ |
0 | 25 |
26 /* should have a generic way to indicate probable size */ | |
27 #define DUMMY_FILE_SIZE (100 * 1024 * 1024) | |
28 #define DUMMY_DURATION 600 /* in seconds */ | |
29 | |
30 #define TAG_END 0 | |
31 #define TAG_SHOWFRAME 1 | |
32 #define TAG_DEFINESHAPE 2 | |
33 #define TAG_FREECHARACTER 3 | |
34 #define TAG_PLACEOBJECT 4 | |
35 #define TAG_REMOVEOBJECT 5 | |
807 | 36 #define TAG_STREAMHEAD 18 |
0 | 37 #define TAG_STREAMBLOCK 19 |
38 #define TAG_JPEG2 21 | |
359 | 39 #define TAG_PLACEOBJECT2 26 |
40 #define TAG_STREAMHEAD2 45 | |
887 | 41 #define TAG_VIDEOSTREAM 60 |
359 | 42 #define TAG_VIDEOFRAME 61 |
2955
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
43 #define TAG_FILEATTRIBUTES 69 |
0 | 44 |
45 #define TAG_LONG 0x100 | |
46 | |
47 /* flags for shape definition */ | |
48 #define FLAG_MOVETO 0x01 | |
49 #define FLAG_SETFILL0 0x02 | |
50 #define FLAG_SETFILL1 0x04 | |
51 | |
359 | 52 #define AUDIO_FIFO_SIZE 65536 |
53 | |
0 | 54 /* character id used */ |
55 #define BITMAP_ID 0 | |
359 | 56 #define VIDEO_ID 0 |
0 | 57 #define SHAPE_ID 1 |
58 | |
516 | 59 #undef NDEBUG |
60 #include <assert.h> | |
359 | 61 |
0 | 62 typedef struct { |
1638 | 63 int audio_stream_index; |
0 | 64 offset_t duration_pos; |
65 offset_t tag_pos; | |
885 | 66 |
359 | 67 int samples_per_frame; |
68 int sound_samples; | |
69 int swf_frame_number; | |
70 int video_frame_number; | |
1889 | 71 int frame_rate; |
0 | 72 int tag; |
359 | 73 |
1854 | 74 uint8_t audio_fifo[AUDIO_FIFO_SIZE]; |
359 | 75 int audio_in_pos; |
76 | |
77 int video_type; | |
78 int audio_type; | |
0 | 79 } SWFContext; |
80 | |
1677
2a85c82b8538
add codec_id <-> codec_tag tables to AVIn/OutputFormat
michael
parents:
1673
diff
changeset
|
81 static const AVCodecTag swf_codec_tags[] = { |
1305 | 82 {CODEC_ID_FLV1, 0x02}, |
83 {CODEC_ID_VP6F, 0x04}, | |
84 {0, 0}, | |
85 }; | |
86 | |
1833 | 87 static const AVCodecTag swf_audio_codec_tags[] = { |
88 {CODEC_ID_PCM_S16LE, 0x00}, | |
89 {CODEC_ID_ADPCM_SWF, 0x01}, | |
90 {CODEC_ID_MP3, 0x02}, | |
91 {CODEC_ID_PCM_S16LE, 0x03}, | |
92 //{CODEC_ID_NELLYMOSER, 0x06}, | |
93 {0, 0}, | |
94 }; | |
95 | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
96 #ifdef CONFIG_MUXERS |
0 | 97 static void put_swf_tag(AVFormatContext *s, int tag) |
98 { | |
99 SWFContext *swf = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
100 ByteIOContext *pb = s->pb; |
0 | 101 |
102 swf->tag_pos = url_ftell(pb); | |
103 swf->tag = tag; | |
104 /* reserve some room for the tag */ | |
105 if (tag & TAG_LONG) { | |
106 put_le16(pb, 0); | |
107 put_le32(pb, 0); | |
108 } else { | |
109 put_le16(pb, 0); | |
110 } | |
111 } | |
112 | |
113 static void put_swf_end_tag(AVFormatContext *s) | |
114 { | |
115 SWFContext *swf = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
116 ByteIOContext *pb = s->pb; |
0 | 117 offset_t pos; |
118 int tag_len, tag; | |
119 | |
120 pos = url_ftell(pb); | |
121 tag_len = pos - swf->tag_pos - 2; | |
122 tag = swf->tag; | |
123 url_fseek(pb, swf->tag_pos, SEEK_SET); | |
124 if (tag & TAG_LONG) { | |
125 tag &= ~TAG_LONG; | |
126 put_le16(pb, (tag << 6) | 0x3f); | |
127 put_le32(pb, tag_len - 4); | |
128 } else { | |
129 assert(tag_len < 0x3f); | |
130 put_le16(pb, (tag << 6) | tag_len); | |
131 } | |
132 url_fseek(pb, pos, SEEK_SET); | |
133 } | |
134 | |
135 static inline void max_nbits(int *nbits_ptr, int val) | |
136 { | |
137 int n; | |
138 | |
139 if (val == 0) | |
140 return; | |
141 val = abs(val); | |
142 n = 1; | |
143 while (val != 0) { | |
144 n++; | |
145 val >>= 1; | |
146 } | |
147 if (n > *nbits_ptr) | |
148 *nbits_ptr = n; | |
149 } | |
150 | |
885 | 151 static void put_swf_rect(ByteIOContext *pb, |
0 | 152 int xmin, int xmax, int ymin, int ymax) |
153 { | |
154 PutBitContext p; | |
65 | 155 uint8_t buf[256]; |
0 | 156 int nbits, mask; |
157 | |
276 | 158 init_put_bits(&p, buf, sizeof(buf)); |
885 | 159 |
0 | 160 nbits = 0; |
161 max_nbits(&nbits, xmin); | |
162 max_nbits(&nbits, xmax); | |
163 max_nbits(&nbits, ymin); | |
164 max_nbits(&nbits, ymax); | |
165 mask = (1 << nbits) - 1; | |
166 | |
167 /* rectangle info */ | |
168 put_bits(&p, 5, nbits); | |
169 put_bits(&p, nbits, xmin & mask); | |
170 put_bits(&p, nbits, xmax & mask); | |
171 put_bits(&p, nbits, ymin & mask); | |
172 put_bits(&p, nbits, ymax & mask); | |
885 | 173 |
0 | 174 flush_put_bits(&p); |
175 put_buffer(pb, buf, pbBufPtr(&p) - p.buf); | |
176 } | |
177 | |
178 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy) | |
179 { | |
180 int nbits, mask; | |
181 | |
182 put_bits(pb, 1, 1); /* edge */ | |
183 put_bits(pb, 1, 1); /* line select */ | |
184 nbits = 2; | |
185 max_nbits(&nbits, dx); | |
186 max_nbits(&nbits, dy); | |
187 | |
188 mask = (1 << nbits) - 1; | |
189 put_bits(pb, 4, nbits - 2); /* 16 bits precision */ | |
190 if (dx == 0) { | |
2308 | 191 put_bits(pb, 1, 0); |
192 put_bits(pb, 1, 1); | |
193 put_bits(pb, nbits, dy & mask); | |
0 | 194 } else if (dy == 0) { |
2308 | 195 put_bits(pb, 1, 0); |
196 put_bits(pb, 1, 0); | |
197 put_bits(pb, nbits, dx & mask); | |
0 | 198 } else { |
2308 | 199 put_bits(pb, 1, 1); |
200 put_bits(pb, nbits, dx & mask); | |
201 put_bits(pb, nbits, dy & mask); | |
0 | 202 } |
203 } | |
204 | |
205 #define FRAC_BITS 16 | |
206 | |
359 | 207 /* put matrix */ |
0 | 208 static void put_swf_matrix(ByteIOContext *pb, |
209 int a, int b, int c, int d, int tx, int ty) | |
210 { | |
211 PutBitContext p; | |
65 | 212 uint8_t buf[256]; |
359 | 213 int nbits; |
0 | 214 |
276 | 215 init_put_bits(&p, buf, sizeof(buf)); |
885 | 216 |
0 | 217 put_bits(&p, 1, 1); /* a, d present */ |
359 | 218 nbits = 1; |
219 max_nbits(&nbits, a); | |
220 max_nbits(&nbits, d); | |
221 put_bits(&p, 5, nbits); /* nb bits */ | |
222 put_bits(&p, nbits, a); | |
223 put_bits(&p, nbits, d); | |
885 | 224 |
0 | 225 put_bits(&p, 1, 1); /* b, c present */ |
359 | 226 nbits = 1; |
227 max_nbits(&nbits, c); | |
228 max_nbits(&nbits, b); | |
229 put_bits(&p, 5, nbits); /* nb bits */ | |
230 put_bits(&p, nbits, c); | |
231 put_bits(&p, nbits, b); | |
0 | 232 |
359 | 233 nbits = 1; |
234 max_nbits(&nbits, tx); | |
235 max_nbits(&nbits, ty); | |
236 put_bits(&p, 5, nbits); /* nb bits */ | |
237 put_bits(&p, nbits, tx); | |
238 put_bits(&p, nbits, ty); | |
0 | 239 |
240 flush_put_bits(&p); | |
241 put_buffer(pb, buf, pbBufPtr(&p) - p.buf); | |
242 } | |
243 | |
359 | 244 /* */ |
0 | 245 static int swf_write_header(AVFormatContext *s) |
246 { | |
1623 | 247 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
248 ByteIOContext *pb = s->pb; |
0 | 249 AVCodecContext *enc, *audio_enc, *video_enc; |
250 PutBitContext p; | |
65 | 251 uint8_t buf1[256]; |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
65
diff
changeset
|
252 int i, width, height, rate, rate_base; |
2955
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
253 int is_avm2; |
0 | 254 |
359 | 255 swf->audio_in_pos = 0; |
256 swf->sound_samples = 0; | |
257 swf->swf_frame_number = 0; | |
258 swf->video_frame_number = 0; | |
259 | |
0 | 260 video_enc = NULL; |
261 audio_enc = NULL; | |
262 for(i=0;i<s->nb_streams;i++) { | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
807
diff
changeset
|
263 enc = s->streams[i]->codec; |
1854 | 264 if (enc->codec_type == CODEC_TYPE_AUDIO) { |
265 if (enc->codec_id == CODEC_ID_MP3) { | |
266 if (!enc->frame_size) { | |
267 av_log(s, AV_LOG_ERROR, "audio frame size not set\n"); | |
268 return -1; | |
269 } | |
270 audio_enc = enc; | |
271 } else { | |
1865 | 272 av_log(s, AV_LOG_ERROR, "SWF muxer only supports MP3\n"); |
1854 | 273 return -1; |
274 } | |
275 } else { | |
2309 | 276 if (enc->codec_id == CODEC_ID_VP6F || |
277 enc->codec_id == CODEC_ID_FLV1 || | |
278 enc->codec_id == CODEC_ID_MJPEG) { | |
359 | 279 video_enc = enc; |
280 } else { | |
1865 | 281 av_log(s, AV_LOG_ERROR, "SWF muxer only supports VP6, FLV1 and MJPEG\n"); |
359 | 282 return -1; |
283 } | |
284 } | |
0 | 285 } |
286 | |
287 if (!video_enc) { | |
2289 | 288 /* currently, cannot work correctly if audio only */ |
359 | 289 swf->video_type = 0; |
0 | 290 width = 320; |
291 height = 200; | |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
65
diff
changeset
|
292 rate = 10; |
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
65
diff
changeset
|
293 rate_base= 1; |
0 | 294 } else { |
359 | 295 swf->video_type = video_enc->codec_id; |
0 | 296 width = video_enc->width; |
297 height = video_enc->height; | |
743 | 298 rate = video_enc->time_base.den; |
299 rate_base = video_enc->time_base.num; | |
0 | 300 } |
301 | |
2309 | 302 if (!audio_enc) { |
359 | 303 swf->audio_type = 0; |
2309 | 304 swf->samples_per_frame = (44100. * rate_base) / rate; |
359 | 305 } else { |
306 swf->audio_type = audio_enc->codec_id; | |
2309 | 307 swf->samples_per_frame = (audio_enc->sample_rate * rate_base) / rate; |
359 | 308 } |
309 | |
2955
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
310 is_avm2 = !strcmp("avm2", s->oformat->name); |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
311 |
0 | 312 put_tag(pb, "FWS"); |
2955
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
313 if (is_avm2) { |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
314 put_byte(pb, 9); |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
315 } else if (video_enc && video_enc->codec_id == CODEC_ID_VP6F) { |
1305 | 316 put_byte(pb, 8); /* version (version 8 and above support VP6 codec) */ |
2309 | 317 } else if (video_enc && video_enc->codec_id == CODEC_ID_FLV1) { |
359 | 318 put_byte(pb, 6); /* version (version 6 and above support FLV1 codec) */ |
319 } else { | |
320 put_byte(pb, 4); /* version (should use 4 for mpeg audio support) */ | |
321 } | |
885 | 322 put_le32(pb, DUMMY_FILE_SIZE); /* dummy size |
323 (will be patched if not streamed) */ | |
0 | 324 |
359 | 325 put_swf_rect(pb, 0, width * 20, 0, height * 20); |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
65
diff
changeset
|
326 put_le16(pb, (rate * 256) / rate_base); /* frame rate */ |
0 | 327 swf->duration_pos = url_ftell(pb); |
85
25062c9b1f86
per context frame_rate_base, this should finally fix frame_rate related av sync issues
michaelni
parents:
65
diff
changeset
|
328 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */ |
885 | 329 |
2955
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
330 /* avm2/swf v9 (also v8?) files require a file attribute tag */ |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
331 if (is_avm2) { |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
332 put_swf_tag(s, TAG_FILEATTRIBUTES); |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
333 put_le32(pb, 1<<3); /* set ActionScript v3/AVM2 flag */ |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
334 put_swf_end_tag(s); |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
335 } |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
336 |
0 | 337 /* define a shape with the jpeg inside */ |
2309 | 338 if (video_enc && (video_enc->codec_id == CODEC_ID_VP6F || |
339 video_enc->codec_id == CODEC_ID_FLV1)) { | |
340 } else if (video_enc && video_enc->codec_id == CODEC_ID_MJPEG) { | |
359 | 341 put_swf_tag(s, TAG_DEFINESHAPE); |
0 | 342 |
359 | 343 put_le16(pb, SHAPE_ID); /* ID of shape */ |
344 /* bounding rectangle */ | |
345 put_swf_rect(pb, 0, width, 0, height); | |
346 /* style info */ | |
347 put_byte(pb, 1); /* one fill style */ | |
348 put_byte(pb, 0x41); /* clipped bitmap fill */ | |
349 put_le16(pb, BITMAP_ID); /* bitmap ID */ | |
350 /* position of the bitmap */ | |
885 | 351 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, |
2308 | 352 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0); |
359 | 353 put_byte(pb, 0); /* no line style */ |
885 | 354 |
359 | 355 /* shape drawing */ |
356 init_put_bits(&p, buf1, sizeof(buf1)); | |
357 put_bits(&p, 4, 1); /* one fill bit */ | |
358 put_bits(&p, 4, 0); /* zero line bit */ | |
885 | 359 |
359 | 360 put_bits(&p, 1, 0); /* not an edge */ |
361 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0); | |
362 put_bits(&p, 5, 1); /* nbits */ | |
363 put_bits(&p, 1, 0); /* X */ | |
364 put_bits(&p, 1, 0); /* Y */ | |
365 put_bits(&p, 1, 1); /* set fill style 1 */ | |
885 | 366 |
359 | 367 /* draw the rectangle ! */ |
368 put_swf_line_edge(&p, width, 0); | |
369 put_swf_line_edge(&p, 0, height); | |
370 put_swf_line_edge(&p, -width, 0); | |
371 put_swf_line_edge(&p, 0, -height); | |
885 | 372 |
359 | 373 /* end of shape */ |
374 put_bits(&p, 1, 0); /* not an edge */ | |
375 put_bits(&p, 5, 0); | |
0 | 376 |
359 | 377 flush_put_bits(&p); |
378 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf); | |
0 | 379 |
359 | 380 put_swf_end_tag(s); |
381 } | |
885 | 382 |
2309 | 383 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3) { |
0 | 384 int v; |
385 | |
386 /* start sound */ | |
359 | 387 put_swf_tag(s, TAG_STREAMHEAD2); |
0 | 388 |
389 v = 0; | |
390 switch(audio_enc->sample_rate) { | |
391 case 11025: | |
392 v |= 1 << 2; | |
393 break; | |
394 case 22050: | |
395 v |= 2 << 2; | |
396 break; | |
397 case 44100: | |
398 v |= 3 << 2; | |
399 break; | |
400 default: | |
401 /* not supported */ | |
2164 | 402 av_log(s, AV_LOG_ERROR, "swf does not support that sample rate, choose from (44100, 22050, 11025).\n"); |
0 | 403 return -1; |
404 } | |
359 | 405 v |= 0x02; /* 16 bit playback */ |
0 | 406 if (audio_enc->channels == 2) |
359 | 407 v |= 0x01; /* stereo playback */ |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
408 put_byte(s->pb, v); |
0 | 409 v |= 0x20; /* mp3 compressed */ |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
410 put_byte(s->pb, v); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
411 put_le16(s->pb, swf->samples_per_frame); /* avg samples per frame */ |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
412 put_le16(s->pb, 0); |
885 | 413 |
0 | 414 put_swf_end_tag(s); |
415 } | |
416 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
417 put_flush_packet(s->pb); |
0 | 418 return 0; |
419 } | |
420 | |
885 | 421 static int swf_write_video(AVFormatContext *s, |
241 | 422 AVCodecContext *enc, const uint8_t *buf, int size) |
0 | 423 { |
359 | 424 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
425 ByteIOContext *pb = s->pb; |
885 | 426 |
359 | 427 /* Flash Player limit */ |
2309 | 428 if (swf->swf_frame_number == 16000) { |
370
845f9de2c883
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
360
diff
changeset
|
429 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); |
359 | 430 } |
0 | 431 |
2309 | 432 if (swf->video_type == CODEC_ID_VP6F || |
433 swf->video_type == CODEC_ID_FLV1) { | |
434 if (swf->video_frame_number == 0) { | |
2308 | 435 /* create a new video object */ |
436 put_swf_tag(s, TAG_VIDEOSTREAM); | |
437 put_le16(pb, VIDEO_ID); | |
2309 | 438 put_le16(pb, 15000); /* hard flash player limit */ |
2308 | 439 put_le16(pb, enc->width); |
440 put_le16(pb, enc->height); | |
441 put_byte(pb, 0); | |
442 put_byte(pb,codec_get_tag(swf_codec_tags,swf->video_type)); | |
443 put_swf_end_tag(s); | |
885 | 444 |
2308 | 445 /* place the video object for the first time */ |
446 put_swf_tag(s, TAG_PLACEOBJECT2); | |
447 put_byte(pb, 0x36); | |
448 put_le16(pb, 1); | |
449 put_le16(pb, VIDEO_ID); | |
450 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0); | |
2309 | 451 put_le16(pb, swf->video_frame_number); |
2308 | 452 put_byte(pb, 'v'); |
453 put_byte(pb, 'i'); | |
454 put_byte(pb, 'd'); | |
455 put_byte(pb, 'e'); | |
456 put_byte(pb, 'o'); | |
457 put_byte(pb, 0x00); | |
458 put_swf_end_tag(s); | |
459 } else { | |
460 /* mark the character for update */ | |
461 put_swf_tag(s, TAG_PLACEOBJECT2); | |
462 put_byte(pb, 0x11); | |
463 put_le16(pb, 1); | |
2309 | 464 put_le16(pb, swf->video_frame_number); |
2308 | 465 put_swf_end_tag(s); |
466 } | |
885 | 467 |
2308 | 468 /* set video frame data */ |
469 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG); | |
470 put_le16(pb, VIDEO_ID); | |
2309 | 471 put_le16(pb, swf->video_frame_number++); |
2308 | 472 put_buffer(pb, buf, size); |
473 put_swf_end_tag(s); | |
2309 | 474 } else if (swf->video_type == CODEC_ID_MJPEG) { |
2308 | 475 if (swf->swf_frame_number > 0) { |
476 /* remove the shape */ | |
477 put_swf_tag(s, TAG_REMOVEOBJECT); | |
478 put_le16(pb, SHAPE_ID); /* shape ID */ | |
479 put_le16(pb, 1); /* depth */ | |
480 put_swf_end_tag(s); | |
885 | 481 |
2308 | 482 /* free the bitmap */ |
483 put_swf_tag(s, TAG_FREECHARACTER); | |
484 put_le16(pb, BITMAP_ID); | |
485 put_swf_end_tag(s); | |
486 } | |
885 | 487 |
2308 | 488 put_swf_tag(s, TAG_JPEG2 | TAG_LONG); |
885 | 489 |
2308 | 490 put_le16(pb, BITMAP_ID); /* ID of the image */ |
885 | 491 |
2308 | 492 /* a dummy jpeg header seems to be required */ |
493 put_byte(pb, 0xff); | |
494 put_byte(pb, 0xd8); | |
495 put_byte(pb, 0xff); | |
496 put_byte(pb, 0xd9); | |
497 /* write the jpeg image */ | |
498 put_buffer(pb, buf, size); | |
885 | 499 |
2308 | 500 put_swf_end_tag(s); |
885 | 501 |
2308 | 502 /* draw the shape */ |
885 | 503 |
2308 | 504 put_swf_tag(s, TAG_PLACEOBJECT); |
505 put_le16(pb, SHAPE_ID); /* shape ID */ | |
506 put_le16(pb, 1); /* depth */ | |
507 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0); | |
508 put_swf_end_tag(s); | |
509 } else { | |
510 /* invalid codec */ | |
511 } | |
885 | 512 |
2308 | 513 swf->swf_frame_number ++; |
0 | 514 |
359 | 515 /* streaming sound always should be placed just before showframe tags */ |
1854 | 516 if (swf->audio_type && swf->audio_in_pos) { |
359 | 517 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG); |
1854 | 518 put_le16(pb, swf->sound_samples); |
519 put_le16(pb, 0); // seek samples | |
520 put_buffer(pb, swf->audio_fifo, swf->audio_in_pos); | |
359 | 521 put_swf_end_tag(s); |
885 | 522 |
359 | 523 /* update FIFO */ |
1854 | 524 swf->sound_samples = 0; |
525 swf->audio_in_pos = 0; | |
359 | 526 } |
527 | |
0 | 528 /* output the frame */ |
529 put_swf_tag(s, TAG_SHOWFRAME); | |
530 put_swf_end_tag(s); | |
885 | 531 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
532 put_flush_packet(s->pb); |
885 | 533 |
0 | 534 return 0; |
535 } | |
536 | |
885 | 537 static int swf_write_audio(AVFormatContext *s, |
359 | 538 AVCodecContext *enc, const uint8_t *buf, int size) |
0 | 539 { |
359 | 540 SWFContext *swf = s->priv_data; |
541 | |
542 /* Flash Player limit */ | |
2309 | 543 if (swf->swf_frame_number == 16000) { |
370
845f9de2c883
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
360
diff
changeset
|
544 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); |
359 | 545 } |
0 | 546 |
1854 | 547 if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) { |
548 av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n"); | |
549 return -1; | |
359 | 550 } |
0 | 551 |
1854 | 552 memcpy(swf->audio_fifo + swf->audio_in_pos, buf, size); |
553 swf->audio_in_pos += size; | |
554 swf->sound_samples += enc->frame_size; | |
555 | |
359 | 556 /* if audio only stream make sure we add swf frames */ |
2309 | 557 if (swf->video_type == 0) { |
359 | 558 swf_write_video(s, enc, 0, 0); |
559 } | |
560 | |
0 | 561 return 0; |
562 } | |
563 | |
468 | 564 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt) |
0 | 565 { |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
807
diff
changeset
|
566 AVCodecContext *codec = s->streams[pkt->stream_index]->codec; |
0 | 567 if (codec->codec_type == CODEC_TYPE_AUDIO) |
468 | 568 return swf_write_audio(s, codec, pkt->data, pkt->size); |
0 | 569 else |
468 | 570 return swf_write_video(s, codec, pkt->data, pkt->size); |
0 | 571 } |
572 | |
573 static int swf_write_trailer(AVFormatContext *s) | |
574 { | |
575 SWFContext *swf = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
576 ByteIOContext *pb = s->pb; |
0 | 577 AVCodecContext *enc, *video_enc; |
578 int file_size, i; | |
579 | |
580 video_enc = NULL; | |
581 for(i=0;i<s->nb_streams;i++) { | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
807
diff
changeset
|
582 enc = s->streams[i]->codec; |
0 | 583 if (enc->codec_type == CODEC_TYPE_VIDEO) |
584 video_enc = enc; | |
585 } | |
586 | |
587 put_swf_tag(s, TAG_END); | |
588 put_swf_end_tag(s); | |
885 | 589 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
590 put_flush_packet(s->pb); |
0 | 591 |
592 /* patch file size and number of frames if not streamed */ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
593 if (!url_is_streamed(s->pb) && video_enc) { |
0 | 594 file_size = url_ftell(pb); |
595 url_fseek(pb, 4, SEEK_SET); | |
596 put_le32(pb, file_size); | |
597 url_fseek(pb, swf->duration_pos, SEEK_SET); | |
598 put_le16(pb, video_enc->frame_number); | |
1643
20c25a594c49
seek back at the end of file after updating header
bcoudurier
parents:
1642
diff
changeset
|
599 url_fseek(pb, file_size, SEEK_SET); |
0 | 600 } |
601 return 0; | |
602 } | |
858
66cc656ea404
Replace CONFIG_ENCODERS/CONFIG_DECODERS with CONFIG_MUXERS/CONFIG_DEMUXERS
diego
parents:
820
diff
changeset
|
603 #endif //CONFIG_MUXERS |
0 | 604 |
359 | 605 /*********************************************/ |
606 /* Extract FLV encoded frame and MP3 from swf | |
607 Note that the detection of the real frame | |
608 is inaccurate at this point as it can be | |
885 | 609 quite tricky to determine, you almost certainly |
359 | 610 will get a bad audio/video sync */ |
0 | 611 |
612 static int get_swf_tag(ByteIOContext *pb, int *len_ptr) | |
613 { | |
614 int tag, len; | |
885 | 615 |
0 | 616 if (url_feof(pb)) |
617 return -1; | |
618 | |
619 tag = get_le16(pb); | |
620 len = tag & 0x3f; | |
621 tag = tag >> 6; | |
622 if (len == 0x3f) { | |
623 len = get_le32(pb); | |
624 } | |
806 | 625 // av_log(NULL, AV_LOG_DEBUG, "Tag: %d - Len: %d\n", tag, len); |
0 | 626 *len_ptr = len; |
627 return tag; | |
628 } | |
629 | |
630 | |
631 static int swf_probe(AVProbeData *p) | |
632 { | |
633 /* check file header */ | |
806 | 634 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' && |
0 | 635 p->buf[2] == 'S') |
636 return AVPROBE_SCORE_MAX; | |
637 else | |
638 return 0; | |
639 } | |
640 | |
641 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
642 { | |
1641 | 643 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
644 ByteIOContext *pb = s->pb; |
2310 | 645 int nbits, len, tag; |
359 | 646 |
806 | 647 tag = get_be32(pb) & 0xffffff00; |
648 | |
2309 | 649 if (tag == MKBETAG('C', 'W', 'S', 0)) { |
887 | 650 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n"); |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
651 return AVERROR(EIO); |
806 | 652 } |
653 if (tag != MKBETAG('F', 'W', 'S', 0)) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
654 return AVERROR(EIO); |
0 | 655 get_le32(pb); |
656 /* skip rectangle size */ | |
657 nbits = get_byte(pb) >> 3; | |
658 len = (4 * nbits - 3 + 7) / 8; | |
659 url_fskip(pb, len); | |
1889 | 660 swf->frame_rate = get_le16(pb); /* 8.8 fixed */ |
0 | 661 get_le16(pb); /* frame count */ |
885 | 662 |
359 | 663 swf->samples_per_frame = 0; |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
664 s->ctx_flags |= AVFMTCTX_NOHEADER; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
665 return 0; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
666 } |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
667 |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
668 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
669 { |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
670 SWFContext *swf = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2402
diff
changeset
|
671 ByteIOContext *pb = s->pb; |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
672 AVStream *vst = NULL, *ast = NULL, *st = 0; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
673 int tag, len, i, frame, v; |
0 | 674 |
675 for(;;) { | |
676 tag = get_swf_tag(pb, &len); | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
677 if (tag < 0) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
678 return AVERROR(EIO); |
2309 | 679 if (tag == TAG_VIDEOSTREAM && !vst) { |
1637 | 680 int ch_id = get_le16(pb); |
359 | 681 get_le16(pb); |
682 get_le16(pb); | |
683 get_le16(pb); | |
684 get_byte(pb); | |
685 /* Check for FLV1 */ | |
1637 | 686 vst = av_new_stream(s, ch_id); |
2913 | 687 if (!vst) |
688 return -1; | |
1635 | 689 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
690 vst->codec->codec_id = codec_get_id(swf_codec_tags, get_byte(pb)); | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
691 av_set_pts_info(vst, 64, 256, swf->frame_rate); |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
692 vst->codec->time_base = (AVRational){ 256, swf->frame_rate }; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
693 len -= 10; |
2309 | 694 } else if ((tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2) && !ast) { |
0 | 695 /* streaming found */ |
1642 | 696 int sample_rate_code; |
0 | 697 get_byte(pb); |
698 v = get_byte(pb); | |
359 | 699 swf->samples_per_frame = get_le16(pb); |
1638 | 700 ast = av_new_stream(s, -1); /* -1 to avoid clash with video stream ch_id */ |
2913 | 701 if (!ast) |
702 return -1; | |
1638 | 703 swf->audio_stream_index = ast->index; |
1636 | 704 ast->codec->channels = 1 + (v&1); |
705 ast->codec->codec_type = CODEC_TYPE_AUDIO; | |
1833 | 706 ast->codec->codec_id = codec_get_id(swf_audio_codec_tags, (v>>4) & 15); |
2023 | 707 ast->need_parsing = AVSTREAM_PARSE_FULL; |
1642 | 708 sample_rate_code= (v>>2) & 3; |
709 if (!sample_rate_code) | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2164
diff
changeset
|
710 return AVERROR(EIO); |
1642 | 711 ast->codec->sample_rate = 11025 << (sample_rate_code-1); |
1890
04f9a3ae30af
seems safer to set pts timebase to sample rate, fix some mp3
bcoudurier
parents:
1889
diff
changeset
|
712 av_set_pts_info(ast, 64, 1, ast->codec->sample_rate); |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
713 len -= 4; |
2308 | 714 } else if (tag == TAG_VIDEOFRAME) { |
1637 | 715 int ch_id = get_le16(pb); |
1639 | 716 len -= 2; |
2309 | 717 for(i=0; i<s->nb_streams; i++) { |
887 | 718 st = s->streams[i]; |
1637 | 719 if (st->codec->codec_type == CODEC_TYPE_VIDEO && st->id == ch_id) { |
720 frame = get_le16(pb); | |
1639 | 721 av_get_packet(pb, pkt, len-2); |
1889 | 722 pkt->pts = frame; |
1637 | 723 pkt->stream_index = st->index; |
724 return pkt->size; | |
359 | 725 } |
885 | 726 } |
359 | 727 } else if (tag == TAG_STREAMBLOCK) { |
1638 | 728 st = s->streams[swf->audio_stream_index]; |
729 if (st->codec->codec_id == CODEC_ID_MP3) { | |
730 url_fskip(pb, 4); | |
731 av_get_packet(pb, pkt, len-4); | |
1833 | 732 } else { // ADPCM, PCM |
733 av_get_packet(pb, pkt, len); | |
359 | 734 } |
1833 | 735 pkt->stream_index = st->index; |
736 return pkt->size; | |
1640 | 737 } else if (tag == TAG_JPEG2) { |
738 for (i=0; i<s->nb_streams; i++) { | |
739 st = s->streams[i]; | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
740 if (st->id == -2) |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
741 break; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
742 } |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
743 if (i == s->nb_streams) { |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
744 vst = av_new_stream(s, -2); /* -2 to avoid clash with video stream and audio stream */ |
2913 | 745 if (!vst) |
746 return -1; | |
2307
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
747 vst->codec->codec_type = CODEC_TYPE_VIDEO; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
748 vst->codec->codec_id = CODEC_ID_MJPEG; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
749 av_set_pts_info(vst, 64, 256, swf->frame_rate); |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
750 vst->codec->time_base = (AVRational){ 256, swf->frame_rate }; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
751 st = vst; |
d5508f387614
add streams on the fly, swf is a streaming format and has no real header, correctly detect audio in RamboMJPEGAVP6_112K.swf now
bcoudurier
parents:
2289
diff
changeset
|
752 } |
2308 | 753 get_le16(pb); /* BITMAP_ID */ |
754 av_new_packet(pkt, len-2); | |
755 get_buffer(pb, pkt->data, 4); | |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
756 if (AV_RB32(pkt->data) == 0xffd8ffd9 || |
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
757 AV_RB32(pkt->data) == 0xffd9ffd8) { |
2308 | 758 /* old SWF files containing SOI/EOI as data start */ |
2402
8decf7585a94
support swink created files which have soi/eoi broken tags reversed
bcoudurier
parents:
2310
diff
changeset
|
759 /* files created by swink have reversed tag */ |
2308 | 760 pkt->size -= 4; |
761 get_buffer(pb, pkt->data, pkt->size); | |
762 } else { | |
763 get_buffer(pb, pkt->data + 4, pkt->size - 4); | |
764 } | |
765 pkt->stream_index = st->index; | |
766 return pkt->size; | |
0 | 767 } |
1639 | 768 url_fskip(pb, len); |
0 | 769 } |
770 return 0; | |
771 } | |
772 | |
773 static int swf_read_close(AVFormatContext *s) | |
774 { | |
2308 | 775 return 0; |
0 | 776 } |
777 | |
1169 | 778 #ifdef CONFIG_SWF_DEMUXER |
779 AVInputFormat swf_demuxer = { | |
0 | 780 "swf", |
781 "Flash format", | |
359 | 782 sizeof(SWFContext), |
0 | 783 swf_probe, |
784 swf_read_header, | |
785 swf_read_packet, | |
786 swf_read_close, | |
787 }; | |
1169 | 788 #endif |
789 #ifdef CONFIG_SWF_MUXER | |
790 AVOutputFormat swf_muxer = { | |
0 | 791 "swf", |
792 "Flash format", | |
793 "application/x-shockwave-flash", | |
794 "swf", | |
795 sizeof(SWFContext), | |
359 | 796 CODEC_ID_MP3, |
797 CODEC_ID_FLV1, | |
0 | 798 swf_write_header, |
799 swf_write_packet, | |
800 swf_write_trailer, | |
801 }; | |
1169 | 802 #endif |
2955
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
803 #ifdef CONFIG_AVM2_MUXER |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
804 AVOutputFormat avm2_muxer = { |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
805 "avm2", |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
806 "Flash 9 (AVM2) format", |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
807 "application/x-shockwave-flash", |
2959
1b7bf70aab74
unset extension, so code path, and guess format do not choose
bcoudurier
parents:
2955
diff
changeset
|
808 NULL, |
2955
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
809 sizeof(SWFContext), |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
810 CODEC_ID_MP3, |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
811 CODEC_ID_FLV1, |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
812 swf_write_header, |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
813 swf_write_packet, |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
814 swf_write_trailer, |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
815 }; |
b2d1cd7ab383
new avm2 (flash 9) muxer, patch by Paul Egan, paulegan at mail dot com
bcoudurier
parents:
2913
diff
changeset
|
816 #endif |