--------------------------------------------------------------------------------------------------
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 #include "avformat.h"00021 #include "bitstream.h"00022 00023 00024 #define DUMMY_FILE_SIZE (100 * 1024 * 1024)00025 #define DUMMY_DURATION 600 00026 00027 #define TAG_END 000028 #define TAG_SHOWFRAME 100029 #define TAG_DEFINESHAPE 200030 #define TAG_FREECHARACTER 300031 #define TAG_PLACEOBJECT 400032 #define TAG_REMOVEOBJECT 500033 #define TAG_STREAMHEAD 1800034 #define TAG_STREAMBLOCK 1900035 #define TAG_JPEG2 2100036 #define TAG_PLACEOBJECT2 2600037 #define TAG_STREAMHEAD2 4500038 #define TAG_VIDEOSTREAM 6000039 #define TAG_VIDEOFRAME 6100040 00041 #define TAG_LONG 0x10000042 00043 00044 #define FLAG_MOVETO 0x0100045 #define FLAG_SETFILL0 0x0200046 #define FLAG_SETFILL1 0x0400047 00048 #define SWF_VIDEO_CODEC_FLV1 0x0200049 00050 #define AUDIO_FIFO_SIZE 6553600051 00052 00053 #define BITMAP_ID 000054 #define VIDEO_ID 000055 #define SHAPE_ID 100056 00057 #undef NDEBUG00058 #include <assert.h>00059 00060 typedef struct {00061 00062 offset_t duration_pos;00063 offset_t tag_pos;00064 00065 int samples_per_frame;00066 int sound_samples;00067 int video_samples;00068 int swf_frame_number;00069 int video_frame_number;00070 int ms_per_frame;00071 int ch_id;00072 int tag;00073 00074 uint8_t *audio_fifo;00075 int audio_in_pos;00076 int audio_out_pos;00077 int audio_size;00078 00079 int video_type;00080 int audio_type;00081 } SWFContext;00082 00083 static const int sSampleRates[3][4] = {00084 {44100, 48000, 32000, 0},00085 {22050, 24000, 16000, 0},00086 {11025, 12000, 8000, 0},00087 };00088 00089 static const int sBitRates[2][3][15] = {00090 { { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},00091 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},00092 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}00093 },00094 { { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},00095 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},00096 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}00097 },00098 };00099 00100 static const int sSamplesPerFrame[3][3] =00101 {00102 { 384, 1152, 1152 },00103 { 384, 1152, 576 },00104 { 384, 1152, 576 }00105 };00106 00107 static const int sBitsPerSlot[3] = {00108 32,00109 8,00110 800111 };00112 00113 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )00114 {00115 uint8_t *dataTmp = (uint8_t *)data;00116 uint32_t header = ( (uint32_t)dataTmp[0] << 24 ) | ( (uint32_t)dataTmp[1] << 16 ) | ( (uint32_t)dataTmp[2] << 8 ) | (uint32_t)dataTmp[3];00117 int layerID = 3 - ((header >> 17) & 0x03);00118 int bitRateID = ((header >> 12) & 0x0f);00119 int sampleRateID = ((header >> 10) & 0x03);00120 int bitRate = 0;00121 int bitsPerSlot = sBitsPerSlot[layerID];00122 int isPadded = ((header >> 9) & 0x01);00123 00124 if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {00125 return 0;00126 }00127 00128 *isMono = ((header >> 6) & 0x03) == 0x03;00129 00130 if ( (header >> 19 ) & 0x01 ) {00131 *sampleRate = sSampleRates[0][sampleRateID];00132 bitRate = sBitRates[0][layerID][bitRateID] * 1000;00133 *samplesPerFrame = sSamplesPerFrame[0][layerID];00134 } else {00135 if ( (header >> 20) & 0x01 ) {00136 *sampleRate = sSampleRates[1][sampleRateID];00137 bitRate = sBitRates[1][layerID][bitRateID] * 1000;00138 *samplesPerFrame = sSamplesPerFrame[1][layerID];00139 } else {00140 *sampleRate = sSampleRates[2][sampleRateID];00141 bitRate = sBitRates[1][layerID][bitRateID] * 1000;00142 *samplesPerFrame = sSamplesPerFrame[2][layerID];00143 }00144 }00145 00146 *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );00147 00148 return 1;00149 }00150 00151 #ifdef CONFIG_ENCODERS00152 static void put_swf_tag(AVFormatContext *s, int tag)00153 {00154 SWFContext *swf = s->priv_data;00155 ByteIOContext *pb = &s->pb;00156 00157 swf->tag_pos = url_ftell(pb);00158 swf->tag = tag;00159 00160 if (tag & TAG_LONG) {00161 put_le16(pb, 0);00162 put_le32(pb, 0);00163 } else {00164 put_le16(pb, 0);00165 }00166 }00167 00168 static void put_swf_end_tag(AVFormatContext *s)00169 {00170 SWFContext *swf = s->priv_data;00171 ByteIOContext *pb = &s->pb;00172 offset_t pos;00173 int tag_len, tag;00174 00175 pos = url_ftell(pb);00176 tag_len = pos - swf->tag_pos - 2;00177 tag = swf->tag;00178 url_fseek(pb, swf->tag_pos, SEEK_SET);00179 if (tag & TAG_LONG) {00180 tag &= ~TAG_LONG;00181 put_le16(pb, (tag << 6) | 0x3f);00182 put_le32(pb, tag_len - 4);00183 } else {00184 assert(tag_len < 0x3f);00185 put_le16(pb, (tag << 6) | tag_len);00186 }00187 url_fseek(pb, pos, SEEK_SET);00188 }00189 00190 static inline void max_nbits(int *nbits_ptr, int val)00191 {00192 int n;00193 00194 if (val == 0)00195 return;00196 val = abs(val);00197 n = 1;00198 while (val != 0) {00199 n++;00200 val >>= 1;00201 }00202 if (n > *nbits_ptr)00203 *nbits_ptr = n;00204 }00205 00206 static void put_swf_rect(ByteIOContext *pb, 00207 int xmin, int xmax, int ymin, int ymax)00208 {00209 PutBitContext p;00210 uint8_t buf[256];00211 int nbits, mask;00212 00213 init_put_bits(&p, buf, sizeof(buf));00214 00215 nbits = 0;00216 max_nbits(&nbits, xmin);00217 max_nbits(&nbits, xmax);00218 max_nbits(&nbits, ymin);00219 max_nbits(&nbits, ymax);00220 mask = (1 << nbits) - 1;00221 00222 00223 put_bits(&p, 5, nbits);00224 put_bits(&p, nbits, xmin & mask);00225 put_bits(&p, nbits, xmax & mask);00226 put_bits(&p, nbits, ymin & mask);00227 put_bits(&p, nbits, ymax & mask);00228 00229 flush_put_bits(&p);00230 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);00231 }00232 00233 static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)00234 {00235 int nbits, mask;00236 00237 put_bits(pb, 1, 1); 00238 put_bits(pb, 1, 1); 00239 nbits = 2;00240 max_nbits(&nbits, dx);00241 max_nbits(&nbits, dy);00242 00243 mask = (1 << nbits) - 1;00244 put_bits(pb, 4, nbits - 2); 00245 if (dx == 0) {00246 put_bits(pb, 1, 0); 00247 put_bits(pb, 1, 1); 00248 put_bits(pb, nbits, dy & mask);00249 } else if (dy == 0) {00250 put_bits(pb, 1, 0); 00251 put_bits(pb, 1, 0); 00252 put_bits(pb, nbits, dx & mask);00253 } else {00254 put_bits(pb, 1, 1); 00255 put_bits(pb, nbits, dx & mask);00256 put_bits(pb, nbits, dy & mask);00257 }00258 }00259 00260 #define FRAC_BITS 1600261 00262 00263 static void put_swf_matrix(ByteIOContext *pb,00264 int a, int b, int c, int d, int tx, int ty)00265 {00266 PutBitContext p;00267 uint8_t buf[256];00268 int nbits;00269 00270 init_put_bits(&p, buf, sizeof(buf));00271 00272 put_bits(&p, 1, 1); 00273 nbits = 1;00274 max_nbits(&nbits, a);00275 max_nbits(&nbits, d);00276 put_bits(&p, 5, nbits); 00277 put_bits(&p, nbits, a);00278 put_bits(&p, nbits, d);00279 00280 put_bits(&p, 1, 1); 00281 nbits = 1;00282 max_nbits(&nbits, c);00283 max_nbits(&nbits, b);00284 put_bits(&p, 5, nbits); 00285 put_bits(&p, nbits, c);00286 put_bits(&p, nbits, b);00287 00288 nbits = 1;00289 max_nbits(&nbits, tx);00290 max_nbits(&nbits, ty);00291 put_bits(&p, 5, nbits); 00292 put_bits(&p, nbits, tx);00293 put_bits(&p, nbits, ty);00294 00295 flush_put_bits(&p);00296 put_buffer(pb, buf, pbBufPtr(&p) - p.buf);00297 }00298 00299 00300 static int swf_write_header(AVFormatContext *s)00301 {00302 SWFContext *swf;00303 ByteIOContext *pb = &s->pb;00304 AVCodecContext *enc, *audio_enc, *video_enc;00305 PutBitContext p;00306 uint8_t buf1[256];00307 int i, width, height, rate, rate_base;00308 00309 swf = av_malloc(sizeof(SWFContext));00310 if (!swf)00311 return -1;00312 s->priv_data = swf;00313 00314 swf->ch_id = -1;00315 swf->audio_in_pos = 0;00316 swf->audio_out_pos = 0;00317 swf->audio_size = 0;00318 swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);00319 swf->sound_samples = 0;00320 swf->video_samples = 0;00321 swf->swf_frame_number = 0;00322 swf->video_frame_number = 0;00323 00324 video_enc = NULL;00325 audio_enc = NULL;00326 for(i=0;i<s->nb_streams;i++) {00327 enc = s->streams[i]->codec;00328 if (enc->codec_type == CODEC_TYPE_AUDIO)00329 audio_enc = enc;00330 else {00331 if ( enc->codec_id == CODEC_ID_FLV1 || enc->codec_id == CODEC_ID_MJPEG ) {00332 video_enc = enc;00333 } else {00334 av_log(enc, AV_LOG_ERROR, "SWF only supports FLV1 and MJPEG\n");00335 return -1;00336 }00337 }00338 }00339 00340 if (!video_enc) {00341 00342 swf->video_type = 0;00343 width = 320;00344 height = 200;00345 rate = 10;00346 rate_base= 1;00347 } else {00348 swf->video_type = video_enc->codec_id;00349 width = video_enc->width;00350 height = video_enc->height;00351 rate = video_enc->time_base.den;00352 rate_base = video_enc->time_base.num;00353 }00354 00355 if (!audio_enc ) {00356 swf->audio_type = 0;00357 swf->samples_per_frame = ( 44100. * rate_base ) / rate;00358 } else {00359 swf->audio_type = audio_enc->codec_id;00360 swf->samples_per_frame = ( ( audio_enc->sample_rate ) * rate_base ) / rate;00361 }00362 00363 put_tag(pb, "FWS");00364 if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {00365 put_byte(pb, 6); 00366 } else {00367 put_byte(pb, 4); 00368 }00369 put_le32(pb, DUMMY_FILE_SIZE); 00370 00371 00372 put_swf_rect(pb, 0, width * 20, 0, height * 20);00373 put_le16(pb, (rate * 256) / rate_base); 00374 swf->duration_pos = url_ftell(pb);00375 put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); 00376 00377 00378 if ( video_enc && video_enc->codec_id == CODEC_ID_FLV1 ) {00379 } else if ( video_enc && video_enc->codec_id == CODEC_ID_MJPEG ) {00380 put_swf_tag(s, TAG_DEFINESHAPE);00381 00382 put_le16(pb, SHAPE_ID); 00383 00384 put_swf_rect(pb, 0, width, 0, height);00385 00386 put_byte(pb, 1); 00387 put_byte(pb, 0x41); 00388 put_le16(pb, BITMAP_ID); 00389 00390 put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, 00391 0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);00392 put_byte(pb, 0); 00393 00394 00395 init_put_bits(&p, buf1, sizeof(buf1));00396 put_bits(&p, 4, 1); 00397 put_bits(&p, 4, 0); 00398 00399 put_bits(&p, 1, 0); 00400 put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);00401 put_bits(&p, 5, 1); 00402 put_bits(&p, 1, 0); 00403 put_bits(&p, 1, 0); 00404 put_bits(&p, 1, 1); 00405 00406 00407 put_swf_line_edge(&p, width, 0);00408 put_swf_line_edge(&p, 0, height);00409 put_swf_line_edge(&p, -width, 0);00410 put_swf_line_edge(&p, 0, -height);00411 00412 00413 put_bits(&p, 1, 0); 00414 put_bits(&p, 5, 0);00415 00416 flush_put_bits(&p);00417 put_buffer(pb, buf1, pbBufPtr(&p) - p.buf);00418 00419 put_swf_end_tag(s);00420 }00421 00422 if (audio_enc && audio_enc->codec_id == CODEC_ID_MP3 ) {00423 int v;00424 00425 00426 put_swf_tag(s, TAG_STREAMHEAD2);00427 00428 v = 0;00429 switch(audio_enc->sample_rate) {00430 case 11025:00431 v |= 1 << 2;00432 break;00433 case 22050:00434 v |= 2 << 2;00435 break;00436 case 44100:00437 v |= 3 << 2;00438 break;00439 default:00440 00441 av_free(swf->audio_fifo);00442 av_free(swf);00443 return -1;00444 }00445 v |= 0x02; 00446 if (audio_enc->channels == 2)00447 v |= 0x01; 00448 put_byte(&s->pb, v);00449 v |= 0x20; 00450 put_byte(&s->pb, v);00451 put_le16(&s->pb, swf->samples_per_frame); 00452 put_le16(&s->pb, 0);00453 00454 put_swf_end_tag(s);00455 }00456 00457 put_flush_packet(&s->pb);00458 return 0;00459 }00460 00461 static int swf_write_video(AVFormatContext *s, 00462 AVCodecContext *enc, const uint8_t *buf, int size)00463 {00464 SWFContext *swf = s->priv_data;00465 ByteIOContext *pb = &s->pb;00466 int c = 0;00467 int outSize = 0;00468 int outSamples = 0;00469 00470 00471 if ( swf->swf_frame_number == 16000 ) {00472 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");00473 }00474 00475 if ( swf->audio_type ) {00476 00477 retry_swf_audio_packet:00478 if ( ( swf->audio_size-outSize ) >= 4 ) {00479 int mp3FrameSize = 0;00480 int mp3SampleRate = 0;00481 int mp3IsMono = 0;00482 int mp3SamplesPerFrame = 0;00483 00484 00485 uint8_t header[4];00486 for (c=0; c<4; c++) {00487 header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];00488 }00489 00490 if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {00491 if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {00492 outSize += mp3FrameSize;00493 outSamples += mp3SamplesPerFrame;00494 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {00495 goto retry_swf_audio_packet;00496 }00497 }00498 } else {00499 00500 00501 00502 swf->audio_in_pos ++;00503 swf->audio_size --;00504 swf->audio_in_pos %= AUDIO_FIFO_SIZE;00505 goto retry_swf_audio_packet;00506 }00507 }00508 00509 00510 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {00511 return 0;00512 }00513 }00514 00515 if ( swf->video_type == CODEC_ID_FLV1 ) {00516 if ( swf->video_frame_number == 0 ) {00517 00518 put_swf_tag(s, TAG_VIDEOSTREAM);00519 put_le16(pb, VIDEO_ID);00520 put_le16(pb, 15000 ); 00521 put_le16(pb, enc->width);00522 put_le16(pb, enc->height);00523 put_byte(pb, 0);00524 put_byte(pb, SWF_VIDEO_CODEC_FLV1);00525 put_swf_end_tag(s);00526 00527 00528 put_swf_tag(s, TAG_PLACEOBJECT2);00529 put_byte(pb, 0x36);00530 put_le16(pb, 1);00531 put_le16(pb, VIDEO_ID);00532 put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);00533 put_le16(pb, swf->video_frame_number );00534 put_byte(pb, 'v');00535 put_byte(pb, 'i');00536 put_byte(pb, 'd');00537 put_byte(pb, 'e');00538 put_byte(pb, 'o');00539 put_byte(pb, 0x00);00540 put_swf_end_tag(s);00541 } else {00542 00543 put_swf_tag(s, TAG_PLACEOBJECT2);00544 put_byte(pb, 0x11);00545 put_le16(pb, 1);00546 put_le16(pb, swf->video_frame_number );00547 put_swf_end_tag(s);00548 }00549 00550 00551 put_swf_tag(s, TAG_VIDEOFRAME | TAG_LONG);00552 put_le16(pb, VIDEO_ID); 00553 put_le16(pb, swf->video_frame_number++ );00554 put_buffer(pb, buf, size);00555 put_swf_end_tag(s);00556 } else if ( swf->video_type == CODEC_ID_MJPEG ) {00557 if (swf->swf_frame_number > 0) {00558 00559 put_swf_tag(s, TAG_REMOVEOBJECT);00560 put_le16(pb, SHAPE_ID); 00561 put_le16(pb, 1); 00562 put_swf_end_tag(s);00563 00564 00565 put_swf_tag(s, TAG_FREECHARACTER);00566 put_le16(pb, BITMAP_ID);00567 put_swf_end_tag(s);00568 }00569 00570 put_swf_tag(s, TAG_JPEG2 | TAG_LONG);00571 00572 put_le16(pb, BITMAP_ID); 00573 00574 00575 put_byte(pb, 0xff); 00576 put_byte(pb, 0xd8);00577 put_byte(pb, 0xff);00578 put_byte(pb, 0xd9);00579 00580 put_buffer(pb, buf, size);00581 00582 put_swf_end_tag(s);00583 00584 00585 00586 put_swf_tag(s, TAG_PLACEOBJECT);00587 put_le16(pb, SHAPE_ID); 00588 put_le16(pb, 1); 00589 put_swf_matrix(pb, 20 << FRAC_BITS, 0, 0, 20 << FRAC_BITS, 0, 0);00590 put_swf_end_tag(s);00591 } else {00592 00593 }00594 00595 swf->swf_frame_number ++;00596 00597 swf->video_samples += swf->samples_per_frame;00598 00599 00600 if ( outSize > 0 ) {00601 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);00602 put_le16(pb, outSamples);00603 put_le16(pb, 0);00604 for (c=0; c<outSize; c++) {00605 put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);00606 }00607 put_swf_end_tag(s);00608 00609 00610 swf->sound_samples += outSamples;00611 swf->audio_in_pos += outSize;00612 swf->audio_size -= outSize;00613 swf->audio_in_pos %= AUDIO_FIFO_SIZE;00614 }00615 00616 00617 put_swf_tag(s, TAG_SHOWFRAME);00618 put_swf_end_tag(s);00619 00620 put_flush_packet(&s->pb);00621 00622 return 0;00623 }00624 00625 static int swf_write_audio(AVFormatContext *s, 00626 AVCodecContext *enc, const uint8_t *buf, int size)00627 {00628 SWFContext *swf = s->priv_data;00629 int c = 0;00630 00631 00632 if ( swf->swf_frame_number == 16000 ) {00633 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");00634 }00635 00636 if (enc->codec_id == CODEC_ID_MP3 ) {00637 for (c=0; c<size; c++) {00638 swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];00639 }00640 swf->audio_size += size;00641 swf->audio_out_pos += size;00642 swf->audio_out_pos %= AUDIO_FIFO_SIZE;00643 }00644 00645 00646 if ( swf->video_type == 0 ) {00647 swf_write_video(s, enc, 0, 0);00648 }00649 00650 return 0;00651 }00652 00653 static int swf_write_packet(AVFormatContext *s, AVPacket *pkt)00654 {00655 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;00656 if (codec->codec_type == CODEC_TYPE_AUDIO)00657 return swf_write_audio(s, codec, pkt->data, pkt->size);00658 else00659 return swf_write_video(s, codec, pkt->data, pkt->size);00660 }00661 00662 static int swf_write_trailer(AVFormatContext *s)00663 {00664 SWFContext *swf = s->priv_data;00665 ByteIOContext *pb = &s->pb;00666 AVCodecContext *enc, *video_enc;00667 int file_size, i;00668 00669 video_enc = NULL;00670 for(i=0;i<s->nb_streams;i++) {00671 enc = s->streams[i]->codec;00672 if (enc->codec_type == CODEC_TYPE_VIDEO)00673 video_enc = enc;00674 }00675 00676 put_swf_tag(s, TAG_END);00677 put_swf_end_tag(s);00678 00679 put_flush_packet(&s->pb);00680 00681 00682 if (!url_is_streamed(&s->pb) && video_enc) {00683 file_size = url_ftell(pb);00684 url_fseek(pb, 4, SEEK_SET);00685 put_le32(pb, file_size);00686 url_fseek(pb, swf->duration_pos, SEEK_SET);00687 put_le16(pb, video_enc->frame_number);00688 }00689 00690 av_free(swf->audio_fifo);00691 00692 return 0;00693 }00694 #endif //CONFIG_ENCODERS00695 00696 00697 00698 00699 00700 00701 00702 00703 static int get_swf_tag(ByteIOContext *pb, int *len_ptr)00704 {00705 int tag, len;00706 00707 if (url_feof(pb))00708 return -1;00709 00710 tag = get_le16(pb);00711 len = tag & 0x3f;00712 tag = tag >> 6;00713 if (len == 0x3f) {00714 len = get_le32(pb);00715 }00716 00717 *len_ptr = len;00718 return tag;00719 }00720 00721 00722 static int swf_probe(AVProbeData *p)00723 {00724 00725 if (p->buf_size <= 16)00726 return 0;00727 if ((p->buf[0] == 'F' || p->buf[0] == 'C') && p->buf[1] == 'W' &&00728 p->buf[2] == 'S')00729 return AVPROBE_SCORE_MAX;00730 else00731 return 0;00732 }00733 00734 static int swf_read_header(AVFormatContext *s, AVFormatParameters *ap)00735 {00736 SWFContext *swf = 0;00737 ByteIOContext *pb = &s->pb;00738 int nbits, len, frame_rate, tag, v;00739 offset_t firstTagOff;00740 AVStream *ast = 0;00741 AVStream *vst = 0;00742 00743 swf = av_malloc(sizeof(SWFContext));00744 if (!swf)00745 return -1;00746 s->priv_data = swf;00747 00748 tag = get_be32(pb) & 0xffffff00;00749 00750 if (tag == MKBETAG('C', 'W', 'S', 0))00751 {00752 av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");00753 return AVERROR_IO;00754 }00755 if (tag != MKBETAG('F', 'W', 'S', 0))00756 return AVERROR_IO;00757 get_le32(pb);00758 00759 nbits = get_byte(pb) >> 3;00760 len = (4 * nbits - 3 + 7) / 8;00761 url_fskip(pb, len);00762 frame_rate = get_le16(pb);00763 get_le16(pb); 00764 00765 00766 00767 00768 swf->ms_per_frame = ( 1000 * 256 ) / frame_rate;00769 swf->samples_per_frame = 0;00770 swf->ch_id = -1;00771 00772 firstTagOff = url_ftell(pb);00773 for(;;) {00774 tag = get_swf_tag(pb, &len);00775 if (tag < 0) {00776 if ( ast || vst ) {00777 if ( vst && ast ) {00778 vst->codec->time_base.den = ast->codec->sample_rate / swf->samples_per_frame;00779 vst->codec->time_base.num = 1;00780 }00781 break;00782 }00783 av_log(s, AV_LOG_ERROR, "No media found in SWF\n");00784 return AVERROR_IO;00785 }00786 if ( tag == TAG_VIDEOSTREAM && !vst) {00787 swf->ch_id = get_le16(pb);00788 get_le16(pb);00789 get_le16(pb);00790 get_le16(pb);00791 get_byte(pb);00792 00793 if ( get_byte(pb) == SWF_VIDEO_CODEC_FLV1 ) {00794 vst = av_new_stream(s, 0);00795 av_set_pts_info(vst, 24, 1, 1000); 00796 00797 vst->codec->codec_type = CODEC_TYPE_VIDEO;00798 vst->codec->codec_id = CODEC_ID_FLV1;00799 if ( swf->samples_per_frame ) {00800 vst->codec->time_base.den = 1000. / swf->ms_per_frame;00801 vst->codec->time_base.num = 1;00802 }00803 }00804 } else if ( ( tag == TAG_STREAMHEAD || tag == TAG_STREAMHEAD2 ) && !ast) {00805 00806 get_byte(pb);00807 v = get_byte(pb);00808 swf->samples_per_frame = get_le16(pb);00809 if (len!=4)00810 url_fskip(pb,len-4);00811 00812 if ((v & 0x20) != 0) {00813 if ( tag == TAG_STREAMHEAD2 ) {00814 get_le16(pb);00815 }00816 ast = av_new_stream(s, 1);00817 av_set_pts_info(ast, 24, 1, 1000); 00818 if (!ast)00819 return -ENOMEM;00820 00821 if (v & 0x01)00822 ast->codec->channels = 2;00823 else00824 ast->codec->channels = 1;00825 00826 switch((v>> 2) & 0x03) {00827 case 1:00828 ast->codec->sample_rate = 11025;00829 break;00830 case 2:00831 ast->codec->sample_rate = 22050;00832 break;00833 case 3:00834 ast->codec->sample_rate = 44100;00835 break;00836 default:00837 av_free(ast);00838 return AVERROR_IO;00839 }00840 ast->codec->codec_type = CODEC_TYPE_AUDIO;00841 ast->codec->codec_id = CODEC_ID_MP3;00842 }00843 } else {00844 url_fskip(pb, len);00845 }00846 }00847 url_fseek(pb, firstTagOff, SEEK_SET);00848 00849 return 0;00850 }00851 00852 static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)00853 {00854 SWFContext *swf = s->priv_data;00855 ByteIOContext *pb = &s->pb;00856 AVStream *st = 0;00857 int tag, len, i, frame;00858 00859 for(;;) {00860 tag = get_swf_tag(pb, &len);00861 if (tag < 0) 00862 return AVERROR_IO;00863 if (tag == TAG_VIDEOFRAME) {00864 for( i=0; i<s->nb_streams; i++ ) {00865 st = s->streams[i];00866 if (st->id == 0) {00867 if ( get_le16(pb) == swf->ch_id ) {00868 frame = get_le16(pb);00869 av_get_packet(pb, pkt, len-4);00870 pkt->pts = frame * swf->ms_per_frame;00871 pkt->stream_index = st->index;00872 return pkt->size;00873 } else {00874 url_fskip(pb, len-2);00875 continue;00876 }00877 }00878 } 00879 url_fskip(pb, len);00880 } else if (tag == TAG_STREAMBLOCK) {00881 for( i=0; i<s->nb_streams; i++ ) {00882 st = s->streams[i];00883 if (st->id == 1) {00884 av_get_packet(pb, pkt, len);00885 pkt->stream_index = st->index;00886 return pkt->size;00887 }00888 }00889 url_fskip(pb, len);00890 } else {00891 url_fskip(pb, len);00892 }00893 }00894 return 0;00895 }00896 00897 static int swf_read_close(AVFormatContext *s)00898 {00899 return 0;00900 }00901 00902 static AVInputFormat swf_iformat = {00903 "swf",00904 "Flash format",00905 sizeof(SWFContext),00906 swf_probe,00907 swf_read_header,00908 swf_read_packet,00909 swf_read_close,00910 };00911 00912 #ifdef CONFIG_ENCODERS00913 static AVOutputFormat swf_oformat = {00914 "swf",00915 "Flash format",00916 "application/x-shockwave-flash",00917 "swf",00918 sizeof(SWFContext),00919 CODEC_ID_MP3,00920 CODEC_ID_FLV1,00921 swf_write_header,00922 swf_write_packet,00923 swf_write_trailer,00924 };00925 #endif //CONFIG_ENCODERS00926 00927 int swf_init(void)00928 {00929 av_register_input_format(&swf_iformat);00930 #ifdef CONFIG_ENCODERS00931 av_register_output_format(&swf_oformat);00932 #endif //CONFIG_ENCODERS00933 return 0;00934 }
|