mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-24 20:19:55 +00:00
simplify swf muxer
Originally committed as revision 8223 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
44e76d6e3b
commit
013e0a8f35
@ -71,7 +71,7 @@ typedef struct {
|
||||
int ms_per_frame;
|
||||
int tag;
|
||||
|
||||
uint8_t *audio_fifo;
|
||||
uint8_t audio_fifo[AUDIO_FIFO_SIZE];
|
||||
int audio_in_pos;
|
||||
int audio_out_pos;
|
||||
int audio_size;
|
||||
@ -95,73 +95,6 @@ static const AVCodecTag swf_audio_codec_tags[] = {
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static const int sSampleRates[3][4] = {
|
||||
{44100, 48000, 32000, 0},
|
||||
{22050, 24000, 16000, 0},
|
||||
{11025, 12000, 8000, 0},
|
||||
};
|
||||
|
||||
static const int sBitRates[2][3][15] = {
|
||||
{ { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448},
|
||||
{ 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384},
|
||||
{ 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}
|
||||
},
|
||||
{ { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256},
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160},
|
||||
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}
|
||||
},
|
||||
};
|
||||
|
||||
static const int sSamplesPerFrame[3][3] =
|
||||
{
|
||||
{ 384, 1152, 1152 },
|
||||
{ 384, 1152, 576 },
|
||||
{ 384, 1152, 576 }
|
||||
};
|
||||
|
||||
static const int sBitsPerSlot[3] = {
|
||||
32,
|
||||
8,
|
||||
8
|
||||
};
|
||||
|
||||
static int swf_mp3_info(void *data, int *byteSize, int *samplesPerFrame, int *sampleRate, int *isMono )
|
||||
{
|
||||
uint32_t header = AV_RB32(data);
|
||||
int layerID = 3 - ((header >> 17) & 0x03);
|
||||
int bitRateID = ((header >> 12) & 0x0f);
|
||||
int sampleRateID = ((header >> 10) & 0x03);
|
||||
int bitRate = 0;
|
||||
int bitsPerSlot = sBitsPerSlot[layerID];
|
||||
int isPadded = ((header >> 9) & 0x01);
|
||||
|
||||
if ( (( header >> 21 ) & 0x7ff) != 0x7ff ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*isMono = ((header >> 6) & 0x03) == 0x03;
|
||||
|
||||
if ( (header >> 19 ) & 0x01 ) {
|
||||
*sampleRate = sSampleRates[0][sampleRateID];
|
||||
bitRate = sBitRates[0][layerID][bitRateID] * 1000;
|
||||
*samplesPerFrame = sSamplesPerFrame[0][layerID];
|
||||
} else {
|
||||
if ( (header >> 20) & 0x01 ) {
|
||||
*sampleRate = sSampleRates[1][sampleRateID];
|
||||
bitRate = sBitRates[1][layerID][bitRateID] * 1000;
|
||||
*samplesPerFrame = sSamplesPerFrame[1][layerID];
|
||||
} else {
|
||||
*sampleRate = sSampleRates[2][sampleRateID];
|
||||
bitRate = sBitRates[1][layerID][bitRateID] * 1000;
|
||||
*samplesPerFrame = sSamplesPerFrame[2][layerID];
|
||||
}
|
||||
}
|
||||
|
||||
*byteSize = ( ( ( ( *samplesPerFrame * (bitRate / bitsPerSlot) ) / *sampleRate ) + isPadded ) );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MUXERS
|
||||
static void put_swf_tag(AVFormatContext *s, int tag)
|
||||
{
|
||||
@ -323,7 +256,6 @@ static int swf_write_header(AVFormatContext *s)
|
||||
swf->audio_in_pos = 0;
|
||||
swf->audio_out_pos = 0;
|
||||
swf->audio_size = 0;
|
||||
swf->audio_fifo = av_malloc(AUDIO_FIFO_SIZE);
|
||||
swf->sound_samples = 0;
|
||||
swf->video_samples = 0;
|
||||
swf->swf_frame_number = 0;
|
||||
@ -333,9 +265,18 @@ static int swf_write_header(AVFormatContext *s)
|
||||
audio_enc = NULL;
|
||||
for(i=0;i<s->nb_streams;i++) {
|
||||
enc = s->streams[i]->codec;
|
||||
if (enc->codec_type == CODEC_TYPE_AUDIO)
|
||||
audio_enc = enc;
|
||||
else {
|
||||
if (enc->codec_type == CODEC_TYPE_AUDIO) {
|
||||
if (enc->codec_id == CODEC_ID_MP3) {
|
||||
if (!enc->frame_size) {
|
||||
av_log(s, AV_LOG_ERROR, "audio frame size not set\n");
|
||||
return -1;
|
||||
}
|
||||
audio_enc = enc;
|
||||
} else {
|
||||
av_log(enc, AV_LOG_ERROR, "SWF only supports MP3\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if ( enc->codec_id == CODEC_ID_VP6F ||
|
||||
enc->codec_id == CODEC_ID_FLV1 ||
|
||||
enc->codec_id == CODEC_ID_MJPEG ) {
|
||||
@ -476,55 +417,12 @@ static int swf_write_video(AVFormatContext *s,
|
||||
{
|
||||
SWFContext *swf = s->priv_data;
|
||||
ByteIOContext *pb = &s->pb;
|
||||
int c = 0;
|
||||
int outSize = 0;
|
||||
int outSamples = 0;
|
||||
|
||||
/* Flash Player limit */
|
||||
if ( swf->swf_frame_number == 16000 ) {
|
||||
av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
|
||||
}
|
||||
|
||||
if ( swf->audio_type ) {
|
||||
/* Prescan audio data for this swf frame */
|
||||
retry_swf_audio_packet:
|
||||
if ( ( swf->audio_size-outSize ) >= 4 ) {
|
||||
int mp3FrameSize = 0;
|
||||
int mp3SampleRate = 0;
|
||||
int mp3IsMono = 0;
|
||||
int mp3SamplesPerFrame = 0;
|
||||
|
||||
/* copy out mp3 header from ring buffer */
|
||||
uint8_t header[4];
|
||||
for (c=0; c<4; c++) {
|
||||
header[c] = swf->audio_fifo[(swf->audio_in_pos+outSize+c) % AUDIO_FIFO_SIZE];
|
||||
}
|
||||
|
||||
if ( swf_mp3_info(header,&mp3FrameSize,&mp3SamplesPerFrame,&mp3SampleRate,&mp3IsMono) ) {
|
||||
if ( ( swf->audio_size-outSize ) >= mp3FrameSize ) {
|
||||
outSize += mp3FrameSize;
|
||||
outSamples += mp3SamplesPerFrame;
|
||||
if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
|
||||
goto retry_swf_audio_packet;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* invalid mp3 data, skip forward
|
||||
we need to do this since the Flash Player
|
||||
does not like custom headers */
|
||||
swf->audio_in_pos ++;
|
||||
swf->audio_size --;
|
||||
swf->audio_in_pos %= AUDIO_FIFO_SIZE;
|
||||
goto retry_swf_audio_packet;
|
||||
}
|
||||
}
|
||||
|
||||
/* audio stream is behind video stream, bail */
|
||||
if ( ( swf->sound_samples + outSamples + swf->samples_per_frame ) < swf->video_samples ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( swf->video_type == CODEC_ID_VP6F ||
|
||||
swf->video_type == CODEC_ID_FLV1 ) {
|
||||
if ( swf->video_frame_number == 0 ) {
|
||||
@ -611,20 +509,16 @@ retry_swf_audio_packet:
|
||||
swf->video_samples += swf->samples_per_frame;
|
||||
|
||||
/* streaming sound always should be placed just before showframe tags */
|
||||
if ( outSize > 0 ) {
|
||||
if (swf->audio_type && swf->audio_in_pos) {
|
||||
put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
|
||||
put_le16(pb, outSamples);
|
||||
put_le16(pb, 0);
|
||||
for (c=0; c<outSize; c++) {
|
||||
put_byte(pb,swf->audio_fifo[(swf->audio_in_pos+c) % AUDIO_FIFO_SIZE]);
|
||||
}
|
||||
put_le16(pb, swf->sound_samples);
|
||||
put_le16(pb, 0); // seek samples
|
||||
put_buffer(pb, swf->audio_fifo, swf->audio_in_pos);
|
||||
put_swf_end_tag(s);
|
||||
|
||||
/* update FIFO */
|
||||
swf->sound_samples += outSamples;
|
||||
swf->audio_in_pos += outSize;
|
||||
swf->audio_size -= outSize;
|
||||
swf->audio_in_pos %= AUDIO_FIFO_SIZE;
|
||||
swf->sound_samples = 0;
|
||||
swf->audio_in_pos = 0;
|
||||
}
|
||||
|
||||
/* output the frame */
|
||||
@ -640,22 +534,21 @@ static int swf_write_audio(AVFormatContext *s,
|
||||
AVCodecContext *enc, const uint8_t *buf, int size)
|
||||
{
|
||||
SWFContext *swf = s->priv_data;
|
||||
int c = 0;
|
||||
|
||||
/* Flash Player limit */
|
||||
if ( swf->swf_frame_number == 16000 ) {
|
||||
av_log(enc, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n");
|
||||
}
|
||||
|
||||
if (enc->codec_id == CODEC_ID_MP3 ) {
|
||||
for (c=0; c<size; c++) {
|
||||
swf->audio_fifo[(swf->audio_out_pos+c)%AUDIO_FIFO_SIZE] = buf[c];
|
||||
}
|
||||
swf->audio_size += size;
|
||||
swf->audio_out_pos += size;
|
||||
swf->audio_out_pos %= AUDIO_FIFO_SIZE;
|
||||
if (swf->audio_in_pos + size >= AUDIO_FIFO_SIZE) {
|
||||
av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(swf->audio_fifo + swf->audio_in_pos, buf, size);
|
||||
swf->audio_in_pos += size;
|
||||
swf->sound_samples += enc->frame_size;
|
||||
|
||||
/* if audio only stream make sure we add swf frames */
|
||||
if ( swf->video_type == 0 ) {
|
||||
swf_write_video(s, enc, 0, 0);
|
||||
@ -701,9 +594,6 @@ static int swf_write_trailer(AVFormatContext *s)
|
||||
put_le16(pb, video_enc->frame_number);
|
||||
url_fseek(pb, file_size, SEEK_SET);
|
||||
}
|
||||
|
||||
av_free(swf->audio_fifo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif //CONFIG_MUXERS
|
||||
|
Loading…
Reference in New Issue
Block a user