diff options
Diffstat (limited to '')
-rw-r--r-- | Game/Code/Classes/UAudio_FFMpeg.pas | 1005 |
1 files changed, 0 insertions, 1005 deletions
diff --git a/Game/Code/Classes/UAudio_FFMpeg.pas b/Game/Code/Classes/UAudio_FFMpeg.pas deleted file mode 100644 index fb25b0f9..00000000 --- a/Game/Code/Classes/UAudio_FFMpeg.pas +++ /dev/null @@ -1,1005 +0,0 @@ -unit UAudio_FFMpeg; - -(******************************************************************************* - -This unit is primarily based upon - - http://www.dranger.com/ffmpeg/ffmpegtutorial_all.html - - and tutorial03.c - - http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html - -*******************************************************************************) - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - - -uses Classes, - {$IFDEF win32} - windows, - {$ENDIF} - Messages, - SysUtils, - {$IFNDEF FPC} - Forms, - {$ENDIF} - SDL, // Used for Audio output Interface - avcodec, // FFMpeg Audio file decoding - avformat, - avutil, - ULog, - UMusic; - -implementation - -uses - {$IFDEF LAZARUS} - lclintf, - {$ifndef win32} - libc, // not available in win32 - {$endif} - {$ENDIF} - portaudio, - UIni, - UMain, - UThemes; - - -type - PPacketQueue = ^TPacketQueue; - TPacketQueue = class - private - firstPkt, - lastPkt : PAVPacketList; - nbPackets : integer; - size : integer; - mutex : PSDL_Mutex; - cond : PSDL_Cond; - quit : boolean; - - public - constructor Create(); - - function Put(pkt : PAVPacket): integer; - function Get(var pkt: TAVPacket; block: boolean): integer; - end; - -type - TStreamStatus = (sNotReady, sStopped, sPlaying, sSeeking, sPaused, sOpen); - -const - StreamStatusStr: array[TStreamStatus] of string = ('Not ready', 'Stopped', 'Playing', 'Seeking', 'Paused', 'Open'); - -type - PAudioBuffer = ^TAudioBuffer; - TAudioBuffer = array[0 .. (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3 div 2)-1] of byte; - -const - SDL_AUDIO_BUFFER_SIZE = 1024; - -type - TFFMpegOutputStream = class(TAudioOutputStream) - private - parseThread: PSDL_Thread; - packetQueue: TPacketQueue; - - status: TStreamStatus; - - // FFMpeg internal data - pFormatCtx : PAVFormatContext; - pCodecCtx : PAVCodecContext; - pCodec : PAVCodec; - ffmpegStreamID : Integer; - ffmpegStream : PAVStream; - - // static vars for AudioDecodeFrame - pkt : TAVPacket; - audio_pkt_data : PChar; - audio_pkt_size : integer; - - // static vars for AudioCallback - audio_buf_index : cardinal; - audio_buf_size : cardinal; - audio_buf : TAudioBuffer; - - paStream : PPaStream; - paFrameSize : integer; - public - constructor Create(); overload; - constructor Create(pFormatCtx: PAVFormatContext; - pCodecCtx: PAVCodecContext; pCodec: PAVCodec; - ffmpegStreamID : Integer; ffmpegStream: PAVStream); overload; - - procedure Play(); - procedure Pause(); - procedure Stop(); - procedure Close(); - - function AudioDecodeFrame(buffer : PUInt8; bufSize: integer): integer; - end; - -type - TAudio_FFMpeg = class( TInterfacedObject, IAudioPlayback ) - private - MusicStream: TFFMpegOutputStream; - - StartSoundStream: TFFMpegOutputStream; - BackSoundStream: TFFMpegOutputStream; - SwooshSoundStream: TFFMpegOutputStream; - ChangeSoundStream: TFFMpegOutputStream; - OptionSoundStream: TFFMpegOutputStream; - ClickSoundStream: TFFMpegOutputStream; - DrumSoundStream: TFFMpegOutputStream; - HihatSoundStream: TFFMpegOutputStream; - ClapSoundStream: TFFMpegOutputStream; - ShuffleSoundStream: TFFMpegOutputStream; - - //Custom Sounds - CustomSounds: array of TCustomSoundEntry; - Loaded: boolean; - Loop: boolean; - - function FindAudioStreamID(pFormatCtx : PAVFormatContext): integer; - public - function GetName: String; - procedure InitializePlayback; - procedure SetVolume(Volume: integer); - procedure SetMusicVolume(Volume: integer); - procedure SetLoop(Enabled: boolean); - function Open(Name: string): boolean; // true if succeed - procedure Rewind; - procedure MoveTo(Time: real); - procedure Play; - procedure Pause; //Pause Mod - procedure Stop; - procedure Close; - function Finished: boolean; - function Length: real; - function getPosition: real; - procedure PlayStart; - procedure PlayBack; - procedure PlaySwoosh; - procedure PlayChange; - procedure PlayOption; - procedure PlayClick; - procedure PlayDrum; - procedure PlayHihat; - procedure PlayClap; - procedure PlayShuffle; - procedure StopShuffle; - - function LoadSoundFromFile(Name: string): TFFMpegOutputStream; - - //Equalizer - function GetFFTData: TFFTData; - - // Interface for Visualizer - function GetPCMData(var data: TPCMData): Cardinal; - - //Custom Sounds - function LoadCustomSound(const Filename: String): Cardinal; - procedure PlayCustomSound(const Index: Cardinal ); - end; - -var - test: TFFMpegOutputStream; - it: integer; - -var - singleton_MusicFFMpeg : IAudioPlayback = nil; - - -function ParseAudio(data: Pointer): integer; cdecl; forward; -procedure SDL_AudioCallback( userdata: Pointer; stream: PUInt8; len: Integer ); cdecl; forward; -function Pa_AudioCallback(input: Pointer; output: Pointer; frameCount: Longword; - timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags; - userData: Pointer): Integer; cdecl; forward; - -constructor TFFMpegOutputStream.Create(); -begin - inherited; - - packetQueue := TPacketQueue.Create(); - - FillChar(pkt, sizeof(TAVPacket), #0); - - status := sStopped; - - audio_pkt_data := nil; - audio_pkt_size := 0; - - audio_buf_index := 0; - audio_buf_size := 0; -end; - -constructor TFFMpegOutputStream.Create(pFormatCtx: PAVFormatContext; - pCodecCtx: PAVCodecContext; pCodec: PAVCodec; - ffmpegStreamID : Integer; ffmpegStream: PAVStream); -begin - Create(); - - Self.pFormatCtx := pFormatCtx; - Self.pCodecCtx := pCodecCtx; - Self.pCodec := pCodec; - Self.ffmpegStreamID := ffmpegStreamID; - Self.ffmpegStream := ffmpegStream; - - test := Self; - it:=0; -end; - -procedure TFFMpegOutputStream.Play(); -var - err: TPaError; -begin - writeln('Play request'); - if(status = sStopped) then - begin - writeln('Play ok'); - status := sPlaying; - Self.parseThread := SDL_CreateThread(@ParseAudio, Self); - //SDL_PauseAudio(0); - - err := Pa_StartStream(Self.paStream); - if(err <> paNoError) then - begin - Writeln('Play: '+ Pa_GetErrorText(err)); - end; - end; -end; - -procedure TFFMpegOutputStream.Pause(); -begin -end; - -procedure TFFMpegOutputStream.Stop(); -begin -end; - -procedure TFFMpegOutputStream.Close(); -begin - // Close the codec - avcodec_close(pCodecCtx); - - // Close the video file - av_close_input_file(pFormatCtx); -end; - - -function TAudio_FFMpeg.GetName: String; -begin - result := 'FFMpeg'; -end; - -procedure TAudio_FFMpeg.InitializePlayback; -begin - Log.LogStatus('InitializePlayback', 'UAudio_FFMpeg'); - - Loaded := false; - Loop := false; - - av_register_all(); - //SDL_Init(SDL_INIT_AUDIO); - Pa_Initialize(); - - StartSoundStream := LoadSoundFromFile(SoundPath + 'Common start.mp3'); - BackSoundStream := LoadSoundFromFile(SoundPath + 'Common back.mp3'); - SwooshSoundStream := LoadSoundFromFile(SoundPath + 'menu swoosh.mp3'); - ChangeSoundStream := LoadSoundFromFile(SoundPath + 'select music change music 50.mp3'); - OptionSoundStream := LoadSoundFromFile(SoundPath + 'option change col.mp3'); - ClickSoundStream := LoadSoundFromFile(SoundPath + 'rimshot022b.mp3'); - -// DrumSoundStream := LoadSoundFromFile(SoundPath + 'bassdrumhard076b.mp3'); -// HihatSoundStream := LoadSoundFromFile(SoundPath + 'hihatclosed068b.mp3'); -// ClapSoundStream := LoadSoundFromFile(SoundPath + 'claps050b.mp3'); - -// ShuffleSoundStream := LoadSoundFromFile(SoundPath + 'Shuffle.mp3'); -end; - - -procedure TAudio_FFMpeg.SetVolume(Volume: integer); -begin - //New: Sets Volume only for this Application -(* - BASS_SetConfig(BASS_CONFIG_GVOL_SAMPLE, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, Volume); - BASS_SetConfig(BASS_CONFIG_GVOL_MUSIC, Volume); -*) -end; - -procedure TAudio_FFMpeg.SetMusicVolume(Volume: Integer); -begin - //Max Volume Prevention - if Volume > 100 then - Volume := 100; - - if Volume < 0 then - Volume := 0; - - - //Set Volume -// BASS_ChannelSetAttributes (Bass, -1, Volume, -101); -end; - -procedure TAudio_FFMpeg.SetLoop(Enabled: boolean); -begin - Loop := Enabled; -end; - -function TAudio_FFMpeg.Open(Name: string): boolean; -begin - Loaded := false; - if FileExists(Name) then - begin -// Bass := Bass_StreamCreateFile(false, pchar(Name), 0, 0, 0); - - Loaded := true; - //Set Max Volume - SetMusicVolume (100); - end; - - Result := Loaded; -end; - -procedure TAudio_FFMpeg.Rewind; -begin - if Loaded then - begin - end; -end; - -procedure TAudio_FFMpeg.MoveTo(Time: real); -var - bytes: integer; -begin -// bytes := BASS_ChannelSeconds2Bytes(Bass, Time); -// BASS_ChannelSetPosition(Bass, bytes); -end; - -procedure TAudio_FFMpeg.Play; -begin - if MusicStream <> nil then - if Loaded then - begin - if Loop then - begin - end; - // start from beginning... - // actually bass itself does not loop, nor does this TAudio_FFMpeg Class - MusicStream.Play(); - end; -end; - -procedure TAudio_FFMpeg.Pause; //Pause Mod -begin - if MusicStream <> nil then - if Loaded then begin - MusicStream.Pause(); // Pauses Song - end; -end; - -procedure TAudio_FFMpeg.Stop; -begin - if MusicStream <> nil then - MusicStream.Stop(); -end; - -procedure TAudio_FFMpeg.Close; -begin - if MusicStream <> nil then - MusicStream.Close(); -end; - -function TAudio_FFMpeg.Length: real; -var - bytes: integer; -begin - Result := 0; - // Todo : why is Music stream always nil !? - - if assigned( MusicStream ) then - begin - Result := MusicStream.pFormatCtx^.duration / AV_TIME_BASE; - end; -end; - -function TAudio_FFMpeg.getPosition: real; -var - bytes: integer; -begin - Result := 0; - -(* - bytes := BASS_ChannelGetPosition(BASS); - Result := BASS_ChannelBytes2Seconds(BASS, bytes); -*) -end; - -function TAudio_FFMpeg.Finished: boolean; -begin - Result := false; - -(* - if BASS_ChannelIsActive(BASS) = BASS_ACTIVE_STOPPED then - begin - Result := true; - end; -*) -end; - -procedure TAudio_FFMpeg.PlayStart; -begin - if StartSoundStream <> nil then - StartSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayBack; -begin - if BackSoundStream <> nil then - BackSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlaySwoosh; -begin - if SwooshSoundStream <> nil then - SwooshSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayChange; -begin - if ChangeSoundStream <> nil then - ChangeSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayOption; -begin - if OptionSoundStream <> nil then - OptionSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayClick; -begin - if ClickSoundStream <> nil then - ClickSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayDrum; -begin - if DrumSoundStream <> nil then - DrumSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayHihat; -begin - if HihatSoundStream <> nil then - HihatSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayClap; -begin - if ClapSoundStream <> nil then - ClapSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.PlayShuffle; -begin - if ShuffleSoundStream <> nil then - ShuffleSoundStream.Play(); -end; - -procedure TAudio_FFMpeg.StopShuffle; -begin - if ShuffleSoundStream <> nil then - ShuffleSoundStream.Stop(); -end; - - -function TFFMpegOutputStream.AudioDecodeFrame(buffer : PUInt8; bufSize: integer): integer; -var - len1, - data_size: integer; -begin - result := -1; - - if (buffer = nil) then - exit; - - while true do - begin - while (audio_pkt_size > 0) do - begin -// writeln( 'got audio packet' ); - data_size := bufSize; - - if(pCodecCtx = nil) then begin -// writeln('Das wars'); - exit; - end; - - // TODO: should be avcodec_decode_audio2 but this wont link on my ubuntu box. - len1 := avcodec_decode_audio(pCodecCtx, Pointer(buffer), - data_size, audio_pkt_data, audio_pkt_size); - - //writeln('avcodec_decode_audio : ' + inttostr( len1 )); - - if(len1 < 0) then - begin - // if error, skip frame -// writeln( 'Skip audio frame' ); - audio_pkt_size := 0; - break; - end; - - Inc(audio_pkt_data, len1); - Dec(audio_pkt_size, len1); - - if (data_size <= 0) then - begin - // No data yet, get more frames - continue; - end; - - // We have data, return it and come back for more later - result := data_size; - exit; - end; - - inc(it); - if (pkt.data <> nil) then - begin - av_free_packet(pkt); - end; - - if (packetQueue.quit) then - begin - result := -1; - exit; - end; -// writeln(it); - if (packetQueue.Get(pkt, true) < 0) then - begin - result := -1; - exit; - end; - - audio_pkt_data := PChar(pkt.data); - audio_pkt_size := pkt.size; -// writeln( 'Audio Packet Size - ' + inttostr(audio_pkt_size) ); - end; -end; - -procedure SDL_AudioCallback(userdata: Pointer; stream: PUInt8; len: Integer); cdecl; -var - outStream : TFFMpegOutputStream; - len1, - audio_size : integer; - pSrc : Pointer; -begin - outStream := TFFMpegOutputStream(userdata); - - while (len > 0) do - with outStream do begin - if (audio_buf_index >= audio_buf_size) then - begin - // We have already sent all our data; get more - audio_size := AudioDecodeFrame(@audio_buf, sizeof(TAudioBuffer)); - //writeln('audio_decode_frame : '+ inttostr(audio_size)); - - if(audio_size < 0) then - begin - // If error, output silence - audio_buf_size := 1024; - FillChar(audio_buf, audio_buf_size, #0); - //writeln( 'Silence' ); - end - else - begin - audio_buf_size := audio_size; - end; - audio_buf_index := 0; - end; - - len1 := audio_buf_size - audio_buf_index; - if (len1 > len) then - len1 := len; - - pSrc := PChar(@audio_buf) + audio_buf_index; - {$ifdef WIN32} - CopyMemory(stream, pSrc , len1); - {$else} - memcpy(stream, pSrc , len1); - {$endif} - - Dec(len, len1); - Inc(stream, len1); - Inc(audio_buf_index, len1); - end; -end; - -function Pa_AudioCallback(input: Pointer; output: Pointer; frameCount: Longword; - timeInfo: PPaStreamCallbackTimeInfo; statusFlags: TPaStreamCallbackFlags; - userData: Pointer): Integer; cdecl; -var - outStream : TFFMpegOutputStream; - len1, - audio_size : integer; - pSrc : Pointer; - len : integer; -begin - outStream := TFFMpegOutputStream(userData); - len := frameCount * outStream.paFrameSize; - - while (len > 0) do - with outStream do begin - if (audio_buf_index >= audio_buf_size) then - begin - // We have already sent all our data; get more - audio_size := AudioDecodeFrame(@audio_buf, sizeof(TAudioBuffer)); - //writeln('audio_decode_frame : '+ inttostr(audio_size)); - - if(audio_size < 0) then - begin - // If error, output silence - audio_buf_size := 1024; - FillChar(audio_buf, audio_buf_size, #0); - //writeln( 'Silence' ); - end - else - begin - audio_buf_size := audio_size; - end; - audio_buf_index := 0; // Todo : jb - SegFault ? - end; - - len1 := audio_buf_size - audio_buf_index; - if (len1 > len) then - len1 := len; - - pSrc := PChar(@audio_buf) + audio_buf_index; - {$ifdef WIN32} - CopyMemory(output, pSrc , len1); - {$else} - memcpy(output, pSrc , len1); - {$endif} - - Dec(len, len1); - Inc(PChar(output), len1); - Inc(audio_buf_index, len1); - end; - - result := paContinue; -end; - -function TAudio_FFMpeg.FindAudioStreamID(pFormatCtx : PAVFormatContext): integer; -var - i : integer; - streamID: integer; - stream : PAVStream; -begin - // Find the first audio stream - streamID := -1; - - for i := 0 to pFormatCtx^.nb_streams-1 do - begin - //Log.LogStatus('aFormatCtx.streams[i] : ' + inttostr(i), 'UAudio_FFMpeg'); - stream := pFormatCtx^.streams[i]; - - if ( stream.codec^.codec_type = CODEC_TYPE_AUDIO ) then - begin - Log.LogStatus('Found Audio Stream', 'UAudio_FFMpeg'); - streamID := i; - break; - end; - end; - - result := streamID; -end; - -function ParseAudio(data: Pointer): integer; cdecl; -var - packet: TAVPacket; - stream: TFFMpegOutputStream; -begin - stream := TFFMpegOutputStream(data); - - while (av_read_frame(stream.pFormatCtx, packet) >= 0) do - begin - //writeln( 'ffmpeg - av_read_frame' ); - - if (packet.stream_index = stream.ffmpegStreamID) then - begin - //writeln( 'packet_queue_put' ); - stream.packetQueue.put(@packet); - end - else - begin - av_free_packet(packet); - end; - end; - - //Writeln('Done: ' + inttostr(stream.packetQueue.nbPackets)); - - result := 0; -end; - - -function TAudio_FFMpeg.LoadSoundFromFile(Name: string): TFFMpegOutputStream; -var - pFormatCtx : PAVFormatContext; - pCodecCtx : PAVCodecContext; - pCodec : PAVCodec; - ffmpegStreamID : Integer; - ffmpegStream : PAVStream; - wanted_spec, - spec : TSDL_AudioSpec; - csIndex : integer; - stream : TFFMpegOutputStream; - err : TPaError; - // move this to a portaudio specific section - paOutParams : TPaStreamParameters; - paApiInfo : PPaHostApiInfo; - paApi : TPaHostApiIndex; - paOutDevice : TPaDeviceIndex; - paOutDeviceInfo : PPaDeviceInfo; -begin - result := nil; - - if (not FileExists(Name)) then - begin - Log.LogStatus('LoadSoundFromFile: Sound not found "' + Name + '"', 'UAudio_FFMpeg'); - writeln('ERROR : LoadSoundFromFile: Sound not found "' + Name + '"', 'UAudio_FFMpeg'); - exit; - end; - - // Open audio file - if (av_open_input_file(pFormatCtx, PChar(Name), nil, 0, nil) > 0) then - exit; - - // Retrieve stream information - if (av_find_stream_info(pFormatCtx) < 0) then - exit; - - dump_format(pFormatCtx, 0, pchar(Name), 0); - - ffmpegStreamID := FindAudioStreamID(pFormatCtx); - if (ffmpegStreamID < 0) then - exit; - - //Log.LogStatus('Audio Stream ID is : '+ inttostr(ffmpegStreamID), 'UAudio_FFMpeg'); - - ffmpegStream := pFormatCtx.streams[ffmpegStreamID]; - pCodecCtx := ffmpegStream^.codec; - - pCodec := avcodec_find_decoder(pCodecCtx^.codec_id); - if (pCodec = nil) then - begin - Log.LogStatus('Unsupported codec!', 'UAudio_FFMpeg'); - exit; - end; - - avcodec_open(pCodecCtx, pCodec); - //writeln( 'Opened the codec' ); - - stream := TFFMpegOutputStream.Create(pFormatCtx, pCodecCtx, pCodec, - ffmpegStreamID, ffmpegStream); - - { - // Set SDL audio settings from codec info - wanted_spec.freq := pCodecCtx^.sample_rate; - wanted_spec.format := AUDIO_S16SYS; - wanted_spec.channels := pCodecCtx^.channels; - wanted_spec.silence := 0; - wanted_spec.samples := SDL_AUDIO_BUFFER_SIZE; - wanted_spec.callback := AudioCallback; - wanted_spec.userdata := stream; - - // TODO: this works only one time (?) - if (SDL_OpenAudio(@wanted_spec, @spec) < 0) then - begin - Log.LogStatus('SDL_OpenAudio: '+SDL_GetError(), 'UAudio_FFMpeg'); - stream.Free(); - exit; - end; - } - - paApi := Pa_HostApiTypeIdToHostApiIndex(paALSA); - paApiInfo := Pa_GetHostApiInfo(paApi); - paOutDevice := paApiInfo^.defaultOutputDevice; - paOutDeviceInfo := Pa_GetDeviceInfo(paOutDevice); - - with paOutParams do begin - device := paOutDevice; - channelCount := pCodecCtx^.channels; - sampleFormat := paInt16; - suggestedLatency := paOutDeviceInfo^.defaultHighOutputLatency; - hostApiSpecificStreamInfo := nil; - end; - - stream.paFrameSize := sizeof(Smallint) * pCodecCtx^.channels; - - err := Pa_OpenStream(stream.paStream, nil, @paOutParams, pCodecCtx^.sample_rate, - paFramesPerBufferUnspecified, //SDL_AUDIO_BUFFER_SIZE div stream.paFrameSize - paNoFlag, @PA_AudioCallback, stream); - if(err <> paNoError) then begin - Log.LogStatus('Pa_OpenDefaultStream: '+Pa_GetErrorText(err), 'UAudio_FFMpeg'); - stream.Free(); - exit; - end; - - Log.LogStatus('Opened audio device', 'UAudio_FFMpeg'); - - //Add CustomSound - csIndex := High(CustomSounds) + 1; - SetLength (CustomSounds, csIndex + 1); - CustomSounds[csIndex].Filename := Name; - CustomSounds[csIndex].Stream := stream; - - result := stream; -end; - -//Equalizer -function TAudio_FFMpeg.GetFFTData: TFFTData; -var - data: TFFTData; -begin - //Get Channel Data Mono and 256 Values -// BASS_ChannelGetData(Bass, @Result, BASS_DATA_FFT512); - result := data; -end; - -// Interface for Visualizer -function TAudio_FFMpeg.GetPCMData(var data: TPCMData): Cardinal; -begin - result := 0; -end; - -function TAudio_FFMpeg.LoadCustomSound(const Filename: String): Cardinal; -var - S: TFFMpegOutputStream; - I: Integer; - F: String; -begin - //Search for Sound in already loaded Sounds - F := UpperCase(SoundPath + FileName); - For I := 0 to High(CustomSounds) do - begin - if (UpperCase(CustomSounds[I].Filename) = F) then - begin - Result := I; - Exit; - end; - end; - - S := LoadSoundFromFile(SoundPath + Filename); - if (S <> nil) then - Result := High(CustomSounds) - else - Result := 0; -end; - -procedure TAudio_FFMpeg.PlayCustomSound(const Index: Cardinal ); -begin - if Index <= High(CustomSounds) then - (CustomSounds[Index].Stream as TFFMpegOutputStream).Play(); -end; - - -constructor TPacketQueue.Create(); -begin - inherited; - - firstPkt := nil; - lastPkt := nil; - nbPackets := 0; - size := 0; - - mutex := SDL_CreateMutex(); - cond := SDL_CreateCond(); -end; - -function TPacketQueue.Put(pkt : PAVPacket): integer; -var - pkt1 : PAVPacketList; -begin - result := -1; - - if (av_dup_packet(pkt) < 0) then - exit; - - pkt1 := av_malloc(sizeof(TAVPacketList)); - if (pkt1 = nil) then - exit; - - pkt1^.pkt := pkt^; - pkt1^.next := nil; - - - SDL_LockMutex(Self.mutex); - try - - if (Self.lastPkt = nil) then - Self.firstPkt := pkt1 - else - Self.lastPkt^.next := pkt1; - - Self.lastPkt := pkt1; - inc(Self.nbPackets); - -// Writeln('Put: ' + inttostr(nbPackets)); - - Self.size := Self.size + pkt1^.pkt.size; - SDL_CondSignal(Self.cond); - - finally - SDL_UnlockMutex(Self.mutex); - end; - - result := 0; -end; - -function TPacketQueue.Get(var pkt: TAVPacket; block: boolean): integer; -var - pkt1 : PAVPacketList; -begin - result := -1; - - SDL_LockMutex(Self.mutex); - try - while true do - begin - if (quit) then - exit; - - pkt1 := Self.firstPkt; - - if (pkt1 <> nil) then - begin - Self.firstPkt := pkt1.next; - if (Self.firstPkt = nil) then - Self.lastPkt := nil; - dec(Self.nbPackets); - -// Writeln('Get: ' + inttostr(nbPackets)); - - Self.size := Self.size - pkt1^.pkt.size; - pkt := pkt1^.pkt; - av_free(pkt1); - - result := 1; - break; - end - else - if (not block) then - begin - result := 0; - break; - end - else - begin - SDL_CondWait(Self.cond, Self.mutex); - end; - end; - finally - SDL_UnlockMutex(Self.mutex); - end; -end; - - - -initialization - singleton_MusicFFMpeg := TAudio_FFMpeg.create(); - - writeln( 'UAudio_FFMpeg - Register Playback' ); - AudioManager.add( IAudioPlayback( singleton_MusicFFMpeg ) ); - -finalization - AudioManager.Remove( IAudioPlayback( singleton_MusicFFMpeg ) ); - - -end. |