Play audio with FFmpeg+OpenAL (delphi)

For the developers that use FFmpeg in their software.
Post Reply
RedCat
Posts: 2
Joined: Sat Feb 24, 2018 5:18 pm

Play audio with FFmpeg+OpenAL (delphi)

Post by RedCat » Mon Mar 05, 2018 7:10 am

I'm trying to Play sound using the OpenAL + FFmpeg bundle I've sorted out the sound, but the sound comes with interruptions, a crash, and it seems not much faster than necessary, the sources is attached,Libraries

Code: Select all

    procedure TOggStream.Open(pFileName : String);
     var
    Res : Integer;
    begin

    if not FileExists(pFileName) then
    begin
    Log.Add('Could not open Ogg file');
    ShowMessage('File not found!');
    Halt(0);
    end;
    OpnFileName:=Pfilename;
    fmt_ctx:=nil;
    log.Clear;
    log.add('FileName = '+OpnFileName);
    if avformat_open_input(fmt_ctx, PANSIChar(AnsiString(OpnFileName)), nil, nil) < 0 then
    begin
      Log.add('Could not open source file '+PANSIChar(AnsiString(OpnFileName)));
      Exit;
    end;
    if avformat_find_stream_info(fmt_ctx , nil) < 0 then
     begin
     Log.add('Could not find stream information '+OpnFileName);
     exit;
    end;

     Log.add('Video:');
     video_index:=  av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nil, 0);
     if video_index < 0 then
     begin
     Log.add(Format('Could not find %s stream in input file ''%s''',
            [string(av_get_media_type_string(AVMEDIA_TYPE_VIDEO)), OpnFileName]));
     Log.add(inttostr(video_index));
     end;
     if video_index>=0 then
     begin
     pStreamVid:=  PPtrIdx(fmt_ctx.streams, video_index);
     dec_ctxVid := pStreamVid.codec;
     avdecVid := avcodec_find_decoder(dec_ctxVid.codec_id);
     if not Assigned(avdecVid) then
     begin
      Log.add(Format('Failed to find %s codec',
              [string(av_get_media_type_string(AVMEDIA_TYPE_VIDEO))]));

     //  Exit;
     end;
     Log.add(avdecVid.long_name);

    if  avcodec_open2(dec_ctxVid,avdecVid,nil)<0 then
    begin
    Log.add(Format('Failed to decode %s With %s codec ',
              [string (OpnFileName), (avdecVid.long_name)]));
    end;
    Log.add(inttostr(dec_ctxVid.width)+'x'+ inttostr(dec_ctxVid.height));
    end;

    Log.add('Audio:');
     audio_index:=  av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, nil, 0);
    if audio_index < 0 then
    begin
    Log.add(Format('Could not find %s stream in input file ''%s''',
            [string(av_get_media_type_string(AVMEDIA_TYPE_AUDIO)), OpnFileName]));
    Log.add(inttostr(audio_index));
    end;
    if audio_index>=0 then
    begin
    pStreamAud:=  PPtrIdx(fmt_ctx.streams, audio_index);
    dec_ctxAud := pStreamAud.codec;
    avdecAud := avcodec_find_decoder(dec_ctxAud.codec_id);
    if not Assigned(avdecAud) then
    begin
      Log.add(Format('Failed to find %s codec',
              [string(av_get_media_type_string(AVMEDIA_TYPE_AUDIO))]));
    end;
     Log.add(avdecAud.long_name);
    end;
    if  avcodec_open2(dec_ctxAud,avdecAud,nil)<0 then
    begin
    Log.add(Format('Failed to decode %s With %s codec ',
              [string (OpnFileName), (avdecAud.long_name)]));
              end;
    audFrame:=avcodec_alloc_frame;
    pict:=avcodec_alloc_frame();
    if not assigned(pict) then
    begin
      Log.add('Could not allocate AVFrame structure');
      exit;
     end;

    if dec_ctxAud.channels = 1 then
    audFormat := AL_FORMAT_MONO16
    else
    audFormat := AL_FORMAT_STEREO16;
    alGenBuffers(2, @Buffers);
    alGenSources(1, @Source);
    alSource3f(source, AL_POSITION, 0, 0, 0);
    alSource3f(source, AL_VELOCITY, 0, 0, 0);
    alSource3f(source, AL_DIRECTION, 0, 0, 0);
    alSourcef(source, AL_ROLLOFF_FACTOR, 0);
    alSourcei(source, AL_SOURCE_RELATIVE, AL_TRUE);
    end;

   
    function TOggStream.Playback : Boolean;
    begin
    if Playing then
    begin
    Result := True;
    exit;
    end;
    if not Stream(Buffers[0]) then
    begin
    Result := False;
    exit;
    end;
    if not Stream(Buffers[1]) then
    begin
    Result := False;
    exit;
    end;
    alSourceQueueBuffers(Source, 2, @Buffers);
    alSourcePlay(Source); 
    Result := True;
    end;

    function TOggStream.Playing : Boolean;
     var
    State : TALEnum;
    begin
    alGetSourcei(Source, AL_SOURCE_STATE, @State);
     Result := (State = AL_PLAYING);
    end;

    function TOggStream.Update : Boolean;
    var
    Processed : Integer;
    Active    : Boolean;
    Buffer    : TALUInt;
    begin
    Active := False;
    alGetSourcei(Source, AL_BUFFERS_PROCESSED, @Processed);
    if Processed > 0 then
     repeat
    alSourceUnqueueBuffers(source, 1, @Buffer);
    Active := Stream(Buffer);
    alSourceQueueBuffers(source, 1, @Buffer);
    dec(Processed);
    until Processed <= 0;
    Result := Active;
    end;

    function TOggStream.Stream(Buffer : TALUInt) : Boolean;
    var
    Data    : PChar;
    Size    : Integer;
    Section : Integer;
    Res     : Integer;
    ff:       integer;
    BufferTMP:array[1..BufferSize+SIZEOF(Integer)] of Integer;
    //   critical : RTL_CRITICAL_SECTION;
    begin
    Size := 0;
    //Res:=0;
    zeroMemory(@BufferTMP,SizeOf(BufferTMP));
    GetMem(Data, BufferSize+SizeOf(Size));
    while (Size < BufferSize) do
    begin
    //InitializeCriticalSection(critical);
    //  EnterCriticalSection(critical);

    av_read_frame(fmt_ctx, @MyPacket);
    begin
    if(MyPacket.stream_index=audio_index) then
      begin
      // Decode video frame
        avcodec_decode_audio4(dec_ctxAud, AudFrame, ff, @MyPacket);

        //sleep(15);
        // Did we get a video frame?
       // if ff>0 then
        //begin
         //FrameFinished:= ff
         Res:=av_samples_get_buffer_size(@AudFrame.linesize[0], dec_ctxAud.channels,Audframe.nb_samples, dec_ctxAud.sample_fmt,1);;
         
        Log.Add( av_get_sample_fmt_name( dec_ctxAud.sample_fmt));

         // CopyMemory(@BufferTmp,Pointer(Integer(AudFrame.data[0])),res);
 	       OldAuddata_size:= MyCircBuf.Write(AudFrame.Data[0],res);
           MyCircBuf.Read(BufferTMP,res);
         // end;
          Application.ProcessMessages;
          end;

         av_free_packet(@MyPacket);
         //LeaveCriticalSection(critical);
         //DeleteCriticalSection(critical);
    end;


    if Res > 0 then
    begin
    inc(Size,Res);
    end
    else
     if Res < 0 then
     Log.Add(ErrorString(Res))
     else
     break;
     end;
     if Size = 0 then
     begin
     Result := False;
     exit;
     end;

     alBufferData(Buffer, AL_FORMAT_STEREO16, @BufferTMP, Size,dec_ctxAud.sample_rate );

     Result := True;
     FreeMem(Data);
     end;
Who faced, help please understand the problem
Attachments
FFMEPG_OPENAL.zip
Sources
(746.29 KiB) Downloaded 15 times

Post Reply