Index: intern/SoundSystem/openal/SND_OpenALDevice.cpp =================================================================== --- intern/SoundSystem/openal/SND_OpenALDevice.cpp (Revision 20555) +++ intern/SoundSystem/openal/SND_OpenALDevice.cpp (Arbeitskopie) @@ -157,6 +157,193 @@ p_i= (char *)&(a); \ s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; } +#define WITH_FFMPEG + +#ifdef WITH_FFMPEG + +extern "C" { +#include +#include +#include +} + +#define SND_SIZE(rate, channels, format) ((((float)rate)*((float)channels)*((float)format))) + +int p_input_callback(void *opaque, uint8_t *buf, int buf_size) +{ + if(**(char***)opaque == (char*)buf) + { + **(char***)opaque += buf_size; + return buf_size; + } + else + return 0; +} + +int FFMPEG_FMT_LEN(SampleFormat fmt) +{ + if(fmt == SAMPLE_FMT_S16) + return 2; + return 1; +} + +uint8_t* resizeBuffer(uint8_t* original, int orig_size, int size) +{ + uint8_t* buffer = (uint8_t*)malloc(size); + memcpy(buffer, original, size < orig_size ? size : orig_size); + free(original); + return buffer; +} + +ALvoid SND_alutLoadWAVMemory(ALbyte *memory,ALsizei memsize,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop) +{ + *format = AL_FORMAT_MONO16; + *data = NULL; + *size = 0; + *freq = 22050; + *loop = AL_FALSE; + + av_register_all(); + + AVProbeData probe_data, *pd = &probe_data; + + pd->filename = ""; + pd->buf = (unsigned char*)memory; + pd->buf_size = memsize; + + AVInputFormat *fmt = av_probe_input_format(pd, 1); + if(!fmt) + return; + + ByteIOContext m_io; + char** opaque = &memory; + + if(init_put_byte(&m_io, (unsigned char*)memory, memsize, 0, &opaque, p_input_callback, NULL, NULL) < 0) + return; + m_io.is_streamed = 1; + + AVFormatContext *pFormatCtx; + if(av_open_input_stream(&pFormatCtx, &m_io, "", fmt, NULL)) + return; + + if(av_find_stream_info(pFormatCtx)<0) + return; + + dump_format(pFormatCtx, 0, "", 0); + + int streamID = -1; + + for(int i = 0; i < pFormatCtx->nb_streams; i++) + if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && streamID < 0) + streamID=i; + if(streamID == -1) + return; + + AVCodecContext* aCodecCtx=pFormatCtx->streams[streamID]->codec; + +// printf("Duration: %d\n", (int)(pFormatCtx->duration*44100.0f/AV_TIME_BASE)); + int aBuffer_size; + if(pFormatCtx->duration > 0) + aBuffer_size = (int)ceil(((float)pFormatCtx->duration)*SND_SIZE(aCodecCtx->sample_rate, aCodecCtx->channels, FFMPEG_FMT_LEN(aCodecCtx->sample_fmt))/((float)AV_TIME_BASE)+((float)AVCODEC_MAX_AUDIO_FRAME_SIZE*6)); + else + aBuffer_size = (int)ceil(SND_SIZE(aCodecCtx->sample_rate, aCodecCtx->channels, FFMPEG_FMT_LEN(aCodecCtx->sample_fmt))+((float)AVCODEC_MAX_AUDIO_FRAME_SIZE*6)); + int aBuffer_index = 0; + uint8_t* aBuffer = (uint8_t*)malloc(aBuffer_size); + + printf("Samplerate: %d\n", aCodecCtx->sample_rate); + printf("Duration: %d\n", pFormatCtx->duration); + printf("Channels: %d\n", aCodecCtx->channels); + printf("Allocated %d Bytes for Buffer\n", aBuffer_size);//*/ + + if((aCodecCtx->channels > 2) || ((aCodecCtx->sample_fmt != SAMPLE_FMT_S16) && (aCodecCtx->sample_fmt != SAMPLE_FMT_S16))) + return; + + AVCodec *aCodec = avcodec_find_decoder(aCodecCtx->codec_id); + if(!aCodec) + return; + + avcodec_open(aCodecCtx, aCodec); + + AVPacket packet; + int audio_pkt_size; + uint8_t *audio_pkt_data; + int data_size, len; + printf("Entering loop!\n"); + + int READ = 0; + + while(av_read_frame(pFormatCtx, &packet)>=0) + { + if(packet.stream_index==streamID) + { + audio_pkt_data = packet.data; + audio_pkt_size = packet.size; + printf("Packet Size: %d, %d!\n", audio_pkt_size, READ); + READ += audio_pkt_size; + while(audio_pkt_size > 0) + { + data_size = aBuffer_size - aBuffer_index; + if(data_size < AVCODEC_MAX_AUDIO_FRAME_SIZE) + { + printf("Resizing!\n"); + aBuffer = resizeBuffer(aBuffer, aBuffer_size, aBuffer_size+AVCODEC_MAX_AUDIO_FRAME_SIZE * 32); + aBuffer_size += AVCODEC_MAX_AUDIO_FRAME_SIZE * 32; + data_size = aBuffer_size - aBuffer_index; + } + printf("Step 1!\n"); + len = avcodec_decode_audio2(aCodecCtx, (int16_t *)(aBuffer + aBuffer_index), &data_size, audio_pkt_data, audio_pkt_size); + printf("Step 2!\n"); + if(len < 0) + { + audio_pkt_size = 0; + break; + } + audio_pkt_data += len; + audio_pkt_size -= len; + if(data_size <= 0) + continue; + aBuffer_index += data_size; + } + } + av_free_packet(&packet); + } + printf("Finished loop!\n"); + + aBuffer = resizeBuffer(aBuffer, aBuffer_size, aBuffer_index); + + *data = aBuffer; + *size = aBuffer_index; + *freq = aCodecCtx->sample_rate; + if(aCodecCtx->channels == 1) + { + switch(aCodecCtx->sample_fmt) + { + case SAMPLE_FMT_U8: + *format = AL_FORMAT_MONO8; + break; + case SAMPLE_FMT_S16: + *format = AL_FORMAT_MONO16; + break; + } + } + else + { + switch(aCodecCtx->sample_fmt) + { + case SAMPLE_FMT_U8: + *format = AL_FORMAT_STEREO8; + break; + case SAMPLE_FMT_S16: + *format = AL_FORMAT_STEREO16; + break; + } + } + + av_close_input_stream(pFormatCtx); +} + +#else + static int stream_read(void *out, ALbyte **stream, ALsizei size, ALsizei *memsize) { if(size <= *memsize) { @@ -293,6 +480,8 @@ } } +#endif + ALvoid SND_alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq) { if (data) @@ -480,8 +669,10 @@ waveslot = m_wavecache->GetWaveSlot(samplename); /* do we support this sample? */ +#ifndef WITH_FFMPEG if (SND_IsSampleValid(name, memlocation)) { +#endif if (waveslot) { bool freemem = false; @@ -546,6 +737,7 @@ /* and free the original stuff (copy was made in openal) */ SND_alutUnloadWAV(sampleformat, data, numberofsamples, samplerate); } +#ifndef WITH_FFMPEG } else { @@ -553,6 +745,7 @@ m_wavecache->RemoveSample(waveslot->GetSampleName(), waveslot->GetBuffer()); waveslot = NULL; } +#endif } return waveslot; } Index: source/blender/src/editsound.c =================================================================== --- source/blender/src/editsound.c (Revision 20555) +++ source/blender/src/editsound.c (Arbeitskopie) @@ -366,6 +366,16 @@ bSample *sample = NULL; int channels, rate, bits, len; +#ifdef WITH_FFMPEG + sample = sound->sample; + sample->channels = 2; + sample->rate = 44100; + sample->bits = 16; + sample->len = 0; + sample->data = malloc(0); + sample->type = SAMPLE_WAV; + return; +#endif /* prepare for the worst... */ sound->sample->type = SAMPLE_INVALID; @@ -499,6 +509,9 @@ /* ugly, but it works (for now) */ static int sound_get_filetype_from_header(bSound *sound, PackedFile *pf) { +#ifdef WITH_FFMPEG + return SAMPLE_WAV; +#endif int filetype = SAMPLE_INVALID; int i; char buffer[25];