comparison swf.c @ 1854:0432f6b969b0 libavformat

simplify swf muxer
author bcoudurier
date Sun, 04 Mar 2007 22:30:25 +0000
parents 09a67819763e
children 908630dcc162
comparison
equal deleted inserted replaced
1853:c704f9d730bf 1854:0432f6b969b0
69 int swf_frame_number; 69 int swf_frame_number;
70 int video_frame_number; 70 int video_frame_number;
71 int ms_per_frame; 71 int ms_per_frame;
72 int tag; 72 int tag;
73 73
74 uint8_t *audio_fifo; 74 uint8_t audio_fifo[AUDIO_FIFO_SIZE];
75 int audio_in_pos; 75 int audio_in_pos;
76 int audio_out_pos; 76 int audio_out_pos;
77 int audio_size; 77 int audio_size;
78 78
79 int video_type; 79 int video_type;
92 {CODEC_ID_MP3, 0x02}, 92 {CODEC_ID_MP3, 0x02},
93 {CODEC_ID_PCM_S16LE, 0x03}, 93 {CODEC_ID_PCM_S16LE, 0x03},
94 //{CODEC_ID_NELLYMOSER, 0x06}, 94 //{CODEC_ID_NELLYMOSER, 0x06},
95 {0, 0}, 95 {0, 0},
96 }; 96 };
97
98 static const int sSampleRates[3][4] = {
99 {44100, 48000, 32000, 0},
100 {22050, 24000, 16000, 0},
101 {11025, 12000, 8000, 0},
102 };
103
104 static const int sBitRates[2][3][15] = {
105 { { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
106 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
107 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
108 },
109 { { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
110 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
111 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
112 },
113 };
114
115 static const int sSamplesPerFrame[3][3] =
116 {
117 { 384, 1152, 1152 },
118 { 384, 1152, 576 },
119 { 384, 1152, 576 }
120 };
121
122 static const int sBitsPerSlot[3] = {
123 32,
124 8,
125 8
126 };
127
128 static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
129 {
130 uint32_t header = AV_RB32(data);
131 int layerID = 3 - ((header >> 17) & 0x03);
132 int bitRateID = ((header >> 12) & 0x0f);
133 int sampleRateID = ((header >> 10) & 0x03);
134 int bitRate = 0;
135 int bitsPerSlot = sBitsPerSlot[layerID];
136 int isPadded = ((header >> 9) & 0x01);
137
138 if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
139 return 0;
140 }
141
142 *isMono = ((header >> 6) & 0x03) == 0x03;
143
144 if ( (header >> 19 ) & 0x01 ) {
145 *sampleRate = sSampleRates[0][sampleRateID];
146 bitRate = sBitRates[0][layerID][bitRateID] * 1000;
147 *samplesPerFrame = sSamplesPerFrame[0][layerID];
148 } else {
149 if ( (header >> 20) & 0x01 ) {
150 *sampleRate = sSampleRates[1][sampleRateID];
151 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
152 *samplesPerFrame = sSamplesPerFrame[1][layerID];
153 } else {
154 *sampleRate = sSampleRates[2][sampleRateID];
155 bitRate = sBitRates[1][layerID][bitRateID] * 1000;
156 *samplesPerFrame = sSamplesPerFrame[2][layerID];
157 }
158 }
159
160 *byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
161
162 return 1;
163 }
164 97
165 #ifdef CONFIG_MUXERS 98 #ifdef CONFIG_MUXERS
166 static void put_swf_tag(AVFormatContext *s, int tag) 99 static void put_swf_tag(AVFormatContext *s, int tag)
167 { 100 {
168 SWFContext *swf = s->priv_data; 101 SWFContext *swf = s->priv_data;
321 int i, width, height, rate, rate_base; 254 int i, width, height, rate, rate_base;
322 255
323 swf->audio_in_pos = 0; 256 swf->audio_in_pos = 0;
324 swf->audio_out_pos = 0; 257 swf->audio_out_pos = 0;
325 swf->audio_size = 0; 258 swf->audio_size = 0;
326 swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
327 swf->sound_samples = 0; 259 swf->sound_samples = 0;
328 swf->video_samples = 0; 260 swf->video_samples = 0;
329 swf->swf_frame_number = 0; 261 swf->swf_frame_number = 0;
330 swf->video_frame_number = 0; 262 swf->video_frame_number = 0;
331 263
332 video_enc = NULL; 264 video_enc = NULL;
333 audio_enc = NULL; 265 audio_enc = NULL;
334 for(i=0;i<s->nb_streams;i++) { 266 for(i=0;i<s->nb_streams;i++) {
335 enc = s->streams[i]->codec; 267 enc = s->streams[i]->codec;
336 if (enc->codec_type == CODEC_TYPE_AUDIO) 268 if (enc->codec_type == CODEC_TYPE_AUDIO) {
337 audio_enc = enc; 269 if (enc->codec_id == CODEC_ID_MP3) {
338 else { 270 if (!enc->frame_size) {
271 av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
272 return -1;
273 }
274 audio_enc = enc;
275 } else {
276 av_log(enc, AV_LOG_ERROR, "SWF only supports MP3\n");
277 return -1;
278 }
279 } else {
339 if ( enc->codec_id == CODEC_ID_VP6F || 280 if ( enc->codec_id == CODEC_ID_VP6F ||
340 enc->codec_id == CODEC_ID_FLV1 || 281 enc->codec_id == CODEC_ID_FLV1 ||
341 enc->codec_id == CODEC_ID_MJPEG ) { 282 enc->codec_id == CODEC_ID_MJPEG ) {
342 video_enc = enc; 283 video_enc = enc;
343 } else { 284 } else {
474 static int swf_write_video(AVFormatContext *s, 415 static int swf_write_video(AVFormatContext *s,
475 AVCodecContext *enc, const uint8_t *buf, int size) 416 AVCodecContext *enc, const uint8_t *buf, int size)
476 { 417 {
477 SWFContext *swf = s->priv_data; 418 SWFContext *swf = s->priv_data;
478 ByteIOContext *pb = &s->pb; 419 ByteIOContext *pb = &s->pb;
479 int c = 0;
480 int outSize = 0;
481 int outSamples = 0;
482 420
483 /* Flash Player limit */ 421 /* Flash Player limit */
484 if ( swf->swf_frame_number == 16000 ) { 422 if ( swf->swf_frame_number == 16000 ) {
485 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); 423 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
486 }
487
488 if ( swf->audio_type ) {
489 /* Prescan audio data for this swf frame */
490 retry_swf_audio_packet:
491 if ( ( swf->audio_size-outSize ) >= 4 ) {
492 int mp3FrameSize = 0;
493 int mp3SampleRate = 0;
494 int mp3IsMono = 0;
495 int mp3SamplesPerFrame = 0;
496
497 /* copy out mp3 header from ring buffer */
498 uint8_t header[4];
499 for (c=0; c<4; c++) {
500 header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
501 }
502
503 if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
504 if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
505 outSize += mp3FrameSize;
506 outSamples += mp3SamplesPerFrame;
507 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
508 goto retry_swf_audio_packet;
509 }
510 }
511 } else {
512 /* invalid mp3 data, skip forward
513 we need to do this since the Flash Player
514 does not like custom headers */
515 swf->audio_in_pos ++;
516 swf->audio_size --;
517 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
518 goto retry_swf_audio_packet;
519 }
520 }
521
522 /* audio stream is behind video stream, bail */
523 if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
524 return 0;
525 }
526 } 424 }
527 425
528 if ( swf->video_type == CODEC_ID_VP6F || 426 if ( swf->video_type == CODEC_ID_VP6F ||
529 swf->video_type == CODEC_ID_FLV1 ) { 427 swf->video_type == CODEC_ID_FLV1 ) {
530 if ( swf->video_frame_number == 0 ) { 428 if ( swf->video_frame_number == 0 ) {
609 swf->swf_frame_number ++; 507 swf->swf_frame_number ++;
610 508
611 swf->video_samples += swf->samples_per_frame; 509 swf->video_samples += swf->samples_per_frame;
612 510
613 /* streaming sound always should be placed just before showframe tags */ 511 /* streaming sound always should be placed just before showframe tags */
614 if ( outSize > 0 ) { 512 if (swf->audio_type && swf->audio_in_pos) {
615 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG); 513 put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
616 put_le16(pb, outSamples); 514 put_le16(pb, swf->sound_samples);
617 put_le16(pb, 0); 515 put_le16(pb, 0); // seek samples
618 for (c=0; c<outSize; c++) { 516 put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
619 put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
620 }
621 put_swf_end_tag(s); 517 put_swf_end_tag(s);
622 518
623 /* update FIFO */ 519 /* update FIFO */
624 swf->sound_samples += outSamples; 520 swf->sound_samples = 0;
625 swf->audio_in_pos += outSize; 521 swf->audio_in_pos = 0;
626 swf->audio_size -= outSize;
627 swf->audio_in_pos %= AUDIO_FIFO_SIZE;
628 } 522 }
629 523
630 /* output the frame */ 524 /* output the frame */
631 put_swf_tag(s, TAG_SHOWFRAME); 525 put_swf_tag(s, TAG_SHOWFRAME);
632 put_swf_end_tag(s); 526 put_swf_end_tag(s);
638 532
639 static int swf_write_audio(AVFormatContext *s, 533 static int swf_write_audio(AVFormatContext *s,
640 AVCodecContext *enc, const uint8_t *buf, int size) 534 AVCodecContext *enc, const uint8_t *buf, int size)
641 { 535 {
642 SWFContext *swf = s->priv_data; 536 SWFContext *swf = s->priv_data;
643 int c = 0;
644 537
645 /* Flash Player limit */ 538 /* Flash Player limit */
646 if ( swf->swf_frame_number == 16000 ) { 539 if ( swf->swf_frame_number == 16000 ) {
647 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); 540 av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
648 } 541 }
649 542
650 if (enc->codec_id == CODEC_ID_MP3 ) { 543 if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
651 for (c=0; c<size; c++) { 544 av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
652 swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c]; 545 return -1;
653 } 546 }
654 swf->audio_size += size; 547
655 swf->audio_out_pos += size; 548 memcpy(swf->audio_fifo + swf->audio_in_pos, buf, size);
656 swf->audio_out_pos %= AUDIO_FIFO_SIZE; 549 swf->audio_in_pos += size;
657 } 550 swf->sound_samples += enc->frame_size;
658 551
659 /* if audio only stream make sure we add swf frames */ 552 /* if audio only stream make sure we add swf frames */
660 if ( swf->video_type == 0 ) { 553 if ( swf->video_type == 0 ) {
661 swf_write_video(s, enc, 0, 0); 554 swf_write_video(s, enc, 0, 0);
662 } 555 }
699 put_le32(pb, file_size); 592 put_le32(pb, file_size);
700 url_fseek(pb, swf->duration_pos, SEEK_SET); 593 url_fseek(pb, swf->duration_pos, SEEK_SET);
701 put_le16(pb, video_enc->frame_number); 594 put_le16(pb, video_enc->frame_number);
702 url_fseek(pb, file_size, SEEK_SET); 595 url_fseek(pb, file_size, SEEK_SET);
703 } 596 }
704
705 av_free(swf->audio_fifo);
706
707 return 0; 597 return 0;
708 } 598 }
709 #endif //CONFIG_MUXERS 599 #endif //CONFIG_MUXERS
710 600
711 /*********************************************/ 601 /*********************************************/