diff --git a/src/lib/ffmpeg-4.0/avcodec.pas b/src/lib/ffmpeg-4.0/avcodec.pas index e1e181363..02c1bbef4 100644 --- a/src/lib/ffmpeg-4.0/avcodec.pas +++ b/src/lib/ffmpeg-4.0/avcodec.pas @@ -59,6 +59,7 @@ TAVPicture = record do_not_instantiate_this_record: incomplete_record; end; PAVPacket = ^TAVPacket; + PPAVPacket = ^PAVPacket; TAVPacket = record we_do_not_use_buf: pointer; pts: cint64; @@ -306,7 +307,6 @@ TAVCodecContext = record do_not_instantiate_this_record: incomplete_record; end; function av_dup_packet(pkt: PAVPacket): cint; cdecl; external av__codec; deprecated; -procedure av_init_packet(var pkt: TAVPacket); cdecl; external av__codec; deprecated; procedure av_free_packet(pkt: PAVPacket); cdecl; external av__codec; deprecated; function avcodec_version(): cuint; cdecl; external av__codec; function av_codec_is_decoder(codec: PAVCodec): cint; cdecl; external av__codec; @@ -325,5 +325,8 @@ function avcodec_send_packet(avctx: PAVCodecContext; avpkt: PAVPacket): cint; cd function avcodec_alloc_context3(codec: PAVCodec): PAVCodecContext; cdecl; external av__codec; procedure avcodec_free_context(avctx: PPAVCodecContext); cdecl; external av__codec; function avcodec_parameters_to_context(codec: PAVCodecContext; par: PAVCodecParameters): cint; cdecl; external av__codec; +function av_packet_alloc(): PAVPacket; cdecl; external av__codec; +procedure av_packet_free(pkt: PPAVPacket); cdecl; external av__codec; +procedure av_packet_unref(pkt: PAVPacket); cdecl; external av__codec; implementation end. diff --git a/src/lib/ffmpeg-4.0/avformat.pas b/src/lib/ffmpeg-4.0/avformat.pas index e47182ad6..2537daca6 100644 --- a/src/lib/ffmpeg-4.0/avformat.pas +++ b/src/lib/ffmpeg-4.0/avformat.pas @@ -54,11 +54,6 @@ interface AVSEEK_FLAG_ANY = 4; AVSEEK_FLAG_BACKWARD = 1; type - PAVPacketList = ^TAVPacketList; - TAVPacketList = record - pkt: TAVPacket; - next: ^TAVPacketList; - end; PAVInputFormat = ^TAVInputFormat; PAVStream = ^TAVStream; PPAVStream = ^PAVStream; @@ -117,7 +112,7 @@ function avformat_version(): cuint; cdecl; external av__format; procedure av_register_all(); cdecl; external av__format; deprecated; function avformat_find_stream_info(ic: PAVFormatContext; options: PPAVDictionary): cint; cdecl; external av__format; function av_stream_get_r_frame_rate(s: PAVStream): TAVRational; cdecl; external av__format; deprecated; -function av_read_frame(s: PAVFormatContext; var pkt: TAVPacket): cint; cdecl; external av__format; +function av_read_frame(s: PAVFormatContext; pkt: PAVPacket): cint; cdecl; external av__format; function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint64; flags: cint): cint; cdecl; external av__format; implementation end. diff --git a/src/lib/ffmpeg-5.0/avcodec.pas b/src/lib/ffmpeg-5.0/avcodec.pas index 32a43557b..8bba2fd72 100644 --- a/src/lib/ffmpeg-5.0/avcodec.pas +++ b/src/lib/ffmpeg-5.0/avcodec.pas @@ -55,6 +55,7 @@ interface AV_CODEC_ID_NONE ); PAVPacket = ^TAVPacket; + PPAVPacket = ^PAVPacket; TAVPacket = record we_do_not_use_buf: pointer; pts: cint64; @@ -271,7 +272,6 @@ TAVCodecContext = record end; function av_packet_ref(dst: PAVPacket; src: PAVPacket): cint; cdecl; external av__codec; procedure av_packet_unref(pkt: PAVPacket); cdecl; external av__codec; -procedure av_init_packet(var pkt: TAVPacket); cdecl; external av__codec; deprecated; function avcodec_version(): cuint; cdecl; external av__codec; function av_codec_is_decoder(codec: PAVCodec): cint; cdecl; external av__codec; function av_codec_iterate(opaque: ppointer): PAVCodec; cdecl; external av__codec; @@ -286,5 +286,7 @@ function avcodec_send_packet(avctx: PAVCodecContext; avpkt: PAVPacket): cint; cd function avcodec_alloc_context3(codec: PAVCodec): PAVCodecContext; cdecl; external av__codec; procedure avcodec_free_context(avctx: PPAVCodecContext); cdecl; external av__codec; function avcodec_parameters_to_context(codec: PAVCodecContext; par: PAVCodecParameters): cint; cdecl; external av__codec; +function av_packet_alloc(): PAVPacket; cdecl; external av__codec; +procedure av_packet_free(pkt: PPAVPacket); cdecl; external av__codec; implementation end. diff --git a/src/lib/ffmpeg-5.0/avformat.pas b/src/lib/ffmpeg-5.0/avformat.pas index 5632778a8..80a7a4eb7 100644 --- a/src/lib/ffmpeg-5.0/avformat.pas +++ b/src/lib/ffmpeg-5.0/avformat.pas @@ -54,11 +54,6 @@ interface AVSEEK_FLAG_ANY = 4; AVSEEK_FLAG_BACKWARD = 1; type - PAVPacketList = ^TAVPacketList; - TAVPacketList = record - pkt: TAVPacket; - next: ^TAVPacketList; - end; PAVInputFormat = ^TAVInputFormat; PAVStream = ^TAVStream; PPAVStream = ^PAVStream; @@ -112,7 +107,7 @@ function avformat_open_input(ps: PPAVFormatContext; url: PAnsiChar; fmt: PAVInpu procedure avformat_close_input(s: PPAVFormatContext); cdecl; external av__format; function avformat_version(): cuint; cdecl; external av__format; function avformat_find_stream_info(ic: PAVFormatContext; options: PPAVDictionary): cint; cdecl; external av__format; -function av_read_frame(s: PAVFormatContext; var pkt: TAVPacket): cint; cdecl; external av__format; +function av_read_frame(s: PAVFormatContext; pkt: PAVPacket): cint; cdecl; external av__format; function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint64; flags: cint): cint; cdecl; external av__format; implementation end. diff --git a/src/lib/ffmpeg-6.0/avcodec.pas b/src/lib/ffmpeg-6.0/avcodec.pas index c37acba94..5a6091f80 100644 --- a/src/lib/ffmpeg-6.0/avcodec.pas +++ b/src/lib/ffmpeg-6.0/avcodec.pas @@ -55,6 +55,7 @@ interface AV_CODEC_ID_NONE ); PAVPacket = ^TAVPacket; + PPAVPacket = ^PAVPacket; TAVPacket = record we_do_not_use_buf: pointer; pts: cint64; @@ -71,11 +72,6 @@ TAVPacket = record we_do_not_use_opaque_ref: pointer; we_do_not_use_time_base: TAVRational; end; - PAVPacketList = ^TAVPacketList; - TAVPacketList = record - pkt: TAVPacket; - next: ^TAVPacketList; - end; PAVCodecDescriptor = ^TAVCodecDescriptor; TAVCodecDescriptor = record we_do_not_use_id: TAVCodecID; @@ -238,7 +234,6 @@ TAVCodecContext = record end; function av_packet_ref(dst: PAVPacket; src: PAVPacket): cint; cdecl; external av__codec; procedure av_packet_unref(pkt: PAVPacket); cdecl; external av__codec; -procedure av_init_packet(var pkt: TAVPacket); cdecl; external av__codec; deprecated; function avcodec_version(): cuint; cdecl; external av__codec; function av_codec_is_decoder(codec: PAVCodec): cint; cdecl; external av__codec; function av_codec_iterate(opaque: ppointer): PAVCodec; cdecl; external av__codec; @@ -253,5 +248,7 @@ function avcodec_send_packet(avctx: PAVCodecContext; avpkt: PAVPacket): cint; cd function avcodec_alloc_context3(codec: PAVCodec): PAVCodecContext; cdecl; external av__codec; procedure avcodec_free_context(avctx: PPAVCodecContext); cdecl; external av__codec; function avcodec_parameters_to_context(codec: PAVCodecContext; par: PAVCodecParameters): cint; cdecl; external av__codec; +function av_packet_alloc(): PAVPacket; cdecl; external av__codec; +procedure av_packet_free(pkt: PPAVPacket); cdecl; external av__codec; implementation end. diff --git a/src/lib/ffmpeg-6.0/avformat.pas b/src/lib/ffmpeg-6.0/avformat.pas index 6fa876015..a56a1ab02 100644 --- a/src/lib/ffmpeg-6.0/avformat.pas +++ b/src/lib/ffmpeg-6.0/avformat.pas @@ -108,7 +108,7 @@ function avformat_open_input(ps: PPAVFormatContext; url: PAnsiChar; fmt: PAVInpu procedure avformat_close_input(s: PPAVFormatContext); cdecl; external av__format; function avformat_version(): cuint; cdecl; external av__format; function avformat_find_stream_info(ic: PAVFormatContext; options: PPAVDictionary): cint; cdecl; external av__format; -function av_read_frame(s: PAVFormatContext; var pkt: TAVPacket): cint; cdecl; external av__format; +function av_read_frame(s: PAVFormatContext; pkt: PAVPacket): cint; cdecl; external av__format; function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint64; flags: cint): cint; cdecl; external av__format; implementation end. diff --git a/src/lib/ffmpeg-7.0/avcodec.pas b/src/lib/ffmpeg-7.0/avcodec.pas index 814519713..a3b6cc188 100644 --- a/src/lib/ffmpeg-7.0/avcodec.pas +++ b/src/lib/ffmpeg-7.0/avcodec.pas @@ -55,6 +55,7 @@ interface AV_CODEC_ID_NONE ); PAVPacket = ^TAVPacket; + PPAVPacket = ^PAVPacket; TAVPacket = record we_do_not_use_buf: pointer; pts: cint64; @@ -70,11 +71,10 @@ TAVPacket = record opaque: pointer; we_do_not_use_opaque_ref: pointer; we_do_not_use_time_base: TAVRational; - end; - PAVPacketList = ^TAVPacketList; - TAVPacketList = record - pkt: TAVPacket; - next: ^TAVPacketList; + (* According to the FFmpeg documentation, sizeof(AVPacket) is + * deprecated for the public ABI. However, TAVPacket is still a member of + * TAVStream. So we can't put the incomplete record member because that will + * change the memory layout of TAVStream *) end; PAVCodecDescriptor = ^TAVCodecDescriptor; TAVCodecDescriptor = record @@ -227,7 +227,6 @@ TAVCodecContext = record end; function av_packet_ref(dst: PAVPacket; src: PAVPacket): cint; cdecl; external av__codec; procedure av_packet_unref(pkt: PAVPacket); cdecl; external av__codec; -procedure av_init_packet(var pkt: TAVPacket); cdecl; external av__codec; deprecated; function avcodec_version(): cuint; cdecl; external av__codec; function av_codec_is_decoder(codec: PAVCodec): cint; cdecl; external av__codec; function av_codec_iterate(opaque: ppointer): PAVCodec; cdecl; external av__codec; @@ -241,5 +240,7 @@ function avcodec_send_packet(avctx: PAVCodecContext; avpkt: PAVPacket): cint; cd function avcodec_alloc_context3(codec: PAVCodec): PAVCodecContext; cdecl; external av__codec; procedure avcodec_free_context(avctx: PPAVCodecContext); cdecl; external av__codec; function avcodec_parameters_to_context(codec: PAVCodecContext; par: PAVCodecParameters): cint; cdecl; external av__codec; +function av_packet_alloc(): PAVPacket; cdecl; external av__codec; +procedure av_packet_free(pkt: PPAVPacket); cdecl; external av__codec; implementation end. diff --git a/src/lib/ffmpeg-7.0/avformat.pas b/src/lib/ffmpeg-7.0/avformat.pas index 85a82a7e7..c020fc1b2 100644 --- a/src/lib/ffmpeg-7.0/avformat.pas +++ b/src/lib/ffmpeg-7.0/avformat.pas @@ -112,7 +112,7 @@ function avformat_open_input(ps: PPAVFormatContext; url: PAnsiChar; fmt: PAVInpu procedure avformat_close_input(s: PPAVFormatContext); cdecl; external av__format; function avformat_version(): cuint; cdecl; external av__format; function avformat_find_stream_info(ic: PAVFormatContext; options: PPAVDictionary): cint; cdecl; external av__format; -function av_read_frame(s: PAVFormatContext; var pkt: TAVPacket): cint; cdecl; external av__format; +function av_read_frame(s: PAVFormatContext; pkt: PAVPacket): cint; cdecl; external av__format; function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint64; flags: cint): cint; cdecl; external av__format; implementation end. diff --git a/src/media/UAudioDecoder_FFmpeg.pas b/src/media/UAudioDecoder_FFmpeg.pas index 3c444a16f..a8d2e4443 100644 --- a/src/media/UAudioDecoder_FFmpeg.pas +++ b/src/media/UAudioDecoder_FFmpeg.pas @@ -132,7 +132,6 @@ TFFmpegDecodeStream = class(TAudioDecodeStream) fDecoderResumeCond: PSDL_Cond; // state-vars for DecodeFrame (locked by DecoderLock) - fAudioPaket: TAVPacket; fAudioPaketSize: integer; fAudioPaketSilence: integer; // number of bytes of silence to return @@ -244,12 +243,6 @@ procedure TFFmpegDecodeStream.Reset(); fParserPauseRequestCount := 0; fDecoderLocked := false; fDecoderPauseRequestCount := 0; - - FillChar(fAudioPaket, SizeOf(TAVPacket), 0); - {$IF (LIBAVFORMAT_VERSION >= 59000000)} - // avoid calling av_packet_unref before fetching first frame - fAudioPaket.data := Pointer(STATUS_PACKET); - {$ENDIF} end; {* @@ -515,14 +508,6 @@ procedure TFFmpegDecodeStream.Close(); fFormatCtx := nil; end; - {$IF (LIBAVFORMAT_VERSION < 59000000)} - if (fAudioPaket.data <> nil) then - av_free_packet(@fAudioPaket); - {$ELSE} - if (PAnsiChar(fAudioPaket.data) <> STATUS_PACKET) then - av_packet_unref(@fAudioPaket); - {$ENDIF} - PerformOnClose(); FreeAndNil(fPacketQueue); @@ -741,7 +726,7 @@ procedure TFFmpegDecodeStream.Parse(); *) function TFFmpegDecodeStream.ParseLoop(): boolean; var - Packet: TAVPacket; + Packet: PAVPacket; SeekTarget: int64; ErrorCode: integer; StartSilence: double; // duration of silence at start of stream @@ -773,6 +758,7 @@ function TFFmpegDecodeStream.ParseLoop(): boolean; begin Result := true; + Packet := nil; while LockParser() do begin @@ -858,6 +844,8 @@ function TFFmpegDecodeStream.ParseLoop(): boolean; Continue; end; + if (Packet = nil) then + Packet := av_packet_alloc(); errnum := av_read_frame(fFormatCtx, Packet); if (errnum < 0) then begin @@ -896,20 +884,20 @@ function TFFmpegDecodeStream.ParseLoop(): boolean; Break; end; - if (Packet.stream_index = fAudioStreamIndex) then - fPacketQueue.Put(@Packet) + if (Packet^.stream_index = fAudioStreamIndex) then + begin + fPacketQueue.Put(Packet); + Packet := nil; + end else - {$IF (LIBAVFORMAT_VERSION < 59000000)} - av_free_packet(@Packet); - {$ELSE} - av_packet_unref(@Packet); - {$ENDIF} + av_packet_unref(Packet); finally SDL_LockMutex(fStateLock); UnlockParser(); end; end; + av_packet_free(@Packet); if (IsQuit()) then begin Result := false; @@ -989,6 +977,7 @@ procedure TFFmpegDecodeStream.FlushCodecBuffers(); function TFFmpegDecodeStream.DecodeFrame(): integer; var + Packet: PAVPacket; PaketDecodedSize: integer; // size of packet data used for decoding DataSize: integer; // size of output data decoded by FFmpeg BlockQueue: boolean; @@ -999,6 +988,7 @@ function TFFmpegDecodeStream.DecodeFrame(): integer; {$ENDIF} begin Result := -1; + Packet := nil; if (EOF) then Exit; @@ -1061,15 +1051,6 @@ function TFFmpegDecodeStream.DecodeFrame(): integer; Exit; end; - // free old packet data - {$IF (LIBAVFORMAT_VERSION < 59000000)} - if (fAudioPaket.data <> nil) then - av_free_packet(@fAudioPaket); - {$ELSE} - if (PAnsiChar(fAudioPaket.data) <> STATUS_PACKET) then - av_packet_unref(@fAudioPaket); - {$ENDIF} - // do not block queue on seeking (to avoid deadlocks on the DecoderLock) if (IsSeeking()) then BlockQueue := false @@ -1078,18 +1059,15 @@ function TFFmpegDecodeStream.DecodeFrame(): integer; // request a new packet and block if none available. // If this fails, the queue was aborted. - if (fPacketQueue.Get(fAudioPaket, BlockQueue) <= 0) then + if (fPacketQueue.Get(Packet, BlockQueue) <= 0) then Exit; // handle Status-packet - if (PAnsiChar(fAudioPaket.data) = STATUS_PACKET) then + if (PAnsiChar(Packet^.data) = STATUS_PACKET) then begin - {$IF (LIBAVFORMAT_VERSION < 59000000)} - fAudioPaket.data := nil; - {$ENDIF} fAudioPaketSize := 0; - case (fAudioPaket.flags) of + case (Packet^.flags) of PKT_STATUS_FLAG_FLUSH: begin // just used if SetPositionIntern was called without the flush flag. @@ -1101,19 +1079,21 @@ function TFFmpegDecodeStream.DecodeFrame(): integer; if (not IsSeeking()) then SetEOF(true); // buffer contains no data -> result = -1 + av_packet_free(@Packet); Exit; end; PKT_STATUS_FLAG_ERROR: begin SetError(true); Log.LogStatus('I/O Error', 'TFFmpegDecodeStream.DecodeFrame'); + av_packet_free(@Packet); Exit; end; PKT_STATUS_FLAG_EMPTY: begin - SilenceDuration := PDouble(fPacketQueue.GetStatusInfo(fAudioPaket))^; + SilenceDuration := PDouble(fPacketQueue.GetStatusInfo(Packet))^; fAudioPaketSilence := Round(SilenceDuration * fFormatInfo.SampleRate) * fFormatInfo.FrameSize; - fPacketQueue.FreeStatusInfo(fAudioPaket); + fPacketQueue.FreeStatusInfo(Packet); end else begin @@ -1121,26 +1101,29 @@ function TFFmpegDecodeStream.DecodeFrame(): integer; end; end; + av_packet_free(@Packet); Continue; end; - fAudioPaketSize := fAudioPaket.size; + fAudioPaketSize := Packet^.size; - avcodec_send_packet(fCodecCtx, @fAudioPaket); + avcodec_send_packet(fCodecCtx, Packet); // if available, update the stream position to the presentation time of this package - if(fAudioPaket.pts <> AV_NOPTS_VALUE) then + if(Packet^.pts <> AV_NOPTS_VALUE) then begin {$IFDEF DebugFFmpegDecode} TmpPos := fAudioStreamPos; {$ENDIF} - fAudioStreamPos := av_q2d(fAudioStream^.time_base) * fAudioPaket.pts; + fAudioStreamPos := av_q2d(fAudioStream^.time_base) * Packet^.pts; {$IFDEF DebugFFmpegDecode} DebugWriteln('Timestamp: ' + floattostrf(fAudioStreamPos, ffFixed, 15, 3) + ' ' + '(Calc: ' + floattostrf(TmpPos, ffFixed, 15, 3) + '), ' + 'Diff: ' + floattostrf(fAudioStreamPos-TmpPos, ffFixed, 15, 3)); {$ENDIF} end; + + av_packet_free(@Packet); end; end; diff --git a/src/media/UMediaCore_FFmpeg.pas b/src/media/UMediaCore_FFmpeg.pas index 41cccf9ec..69cf99d37 100644 --- a/src/media/UMediaCore_FFmpeg.pas +++ b/src/media/UMediaCore_FFmpeg.pas @@ -47,11 +47,16 @@ interface UPath; type + PPacketList = ^TPacketList; + TPacketList = record + pkt: PAVPacket; + next: ^TPacketList; + end; PPacketQueue = ^TPacketQueue; TPacketQueue = class private - FirstListEntry: PAVPacketList; - LastListEntry: PAVPacketList; + FirstListEntry: PPacketList; + LastListEntry: PPacketList; PacketCount: integer; Mutex: PSDL_Mutex; Condition: PSDL_Cond; @@ -63,9 +68,9 @@ TPacketQueue = class function Put(Packet : PAVPacket): integer; function PutStatus(StatusFlag: integer; StatusInfo: Pointer): integer; - procedure FreeStatusInfo(var Packet: TAVPacket); - function GetStatusInfo(var Packet: TAVPacket): Pointer; - function Get(var Packet: TAVPacket; Blocking: boolean): integer; + procedure FreeStatusInfo(Packet: PAVPacket); + function GetStatusInfo(Packet: PAVPacket): Pointer; + function Get(var Packet: PAVPacket; Blocking: boolean): integer; function GetSize(): integer; procedure Flush(); procedure Abort(); @@ -511,20 +516,21 @@ function TPacketQueue.IsAborted(): boolean; SDL_UnlockMutex(Mutex); end; +// The queue will take over memory management of Packet (should not be freed by caller) function TPacketQueue.Put(Packet : PAVPacket): integer; var - CurrentListEntry : PAVPacketList; + CurrentListEntry : PPacketList; begin Result := -1; if (Packet = nil) then Exit; - CurrentListEntry := av_malloc(SizeOf(TAVPacketList)); + New(CurrentListEntry); if (CurrentListEntry = nil) then Exit; - CurrentListEntry^.pkt := Packet^; + CurrentListEntry^.pkt := Packet; {$IF LIBAVFORMAT_VERSION < 59000000} if (PChar(Packet^.data) <> STATUS_PACKET) then begin @@ -549,7 +555,7 @@ function TPacketQueue.Put(Packet : PAVPacket): integer; LastListEntry := CurrentListEntry; Inc(PacketCount); - Size := Size + CurrentListEntry^.pkt.size; + Size := Size + CurrentListEntry^.pkt^.size; SDL_CondSignal(Condition); finally SDL_UnlockMutex(Mutex); @@ -568,54 +574,49 @@ function TPacketQueue.Put(Packet : PAVPacket): integer; *) function TPacketQueue.PutStatus(StatusFlag: integer; StatusInfo: Pointer): integer; var - TempPacket: PAVPacket; + Packet: PAVPacket; begin - // create temp. package - TempPacket := av_malloc(SizeOf(TAVPacket)); - if (TempPacket = nil) then + Packet := av_packet_alloc(); + if (Packet = nil) then begin Result := -1; Exit; end; - // init package - av_init_packet(TempPacket^); - TempPacket^.data := Pointer(STATUS_PACKET); - TempPacket^.flags := StatusFlag; + + Packet^.data := Pointer(STATUS_PACKET); + Packet^.flags := StatusFlag; {$IF LIBAVCODEC_VERSION_MAJOR >= 59} - TempPacket^.opaque := StatusInfo; + Packet^.opaque := StatusInfo; {$ELSE} - TempPacket^.side_data := StatusInfo; + Packet^.side_data := StatusInfo; {$ENDIF} - // put a copy of the package into the queue - Result := Put(TempPacket); - // data has been copied -> delete temp. package - av_free(TempPacket); + + Result := Put(Packet); end; -procedure TPacketQueue.FreeStatusInfo(var Packet: TAVPacket); +procedure TPacketQueue.FreeStatusInfo(Packet: PAVPacket); begin {$IF LIBAVCODEC_VERSION_MAJOR >= 59} - if (Packet.opaque <> nil) then - FreeMem(Packet.opaque); + FreeMemAndNil(Packet^.opaque); {$ELSE} - if (Packet.side_data <> nil) then - FreeMem(Packet.side_data); + FreeMemAndNil(Packet^.side_data); {$ENDIF} end; -function TPacketQueue.GetStatusInfo(var Packet: TAVPacket): Pointer; +function TPacketQueue.GetStatusInfo(Packet: PAVPacket): Pointer; begin {$IF LIBAVCODEC_VERSION_MAJOR >= 59} - Result := Packet.opaque; + Result := Packet^.opaque; {$ELSE} - Result := Packet.side_data; + Result := Packet^.side_data; {$ENDIF} end; -function TPacketQueue.Get(var Packet: TAVPacket; Blocking: boolean): integer; +// The caller takes over memory management of Packet +function TPacketQueue.Get(var Packet: PAVPacket; Blocking: boolean): integer; var - CurrentListEntry: PAVPacketList; + CurrentListEntry: PPacketList; const WAIT_TIMEOUT = 10; // timeout in ms begin @@ -636,9 +637,9 @@ function TPacketQueue.Get(var Packet: TAVPacket; Blocking: boolean): integer; LastListEntry := nil; Dec(PacketCount); - Size := Size - CurrentListEntry^.pkt.size; + Size := Size - CurrentListEntry^.pkt^.size; Packet := CurrentListEntry^.pkt; - av_free(CurrentListEntry); + Dispose(CurrentListEntry); Result := 1; Break; @@ -673,7 +674,7 @@ function TPacketQueue.GetSize(): integer; procedure TPacketQueue.Flush(); var - CurrentListEntry, TempListEntry: PAVPacketList; + CurrentListEntry, TempListEntry: PPacketList; begin SDL_LockMutex(Mutex); @@ -682,17 +683,13 @@ procedure TPacketQueue.Flush(); begin TempListEntry := CurrentListEntry^.next; // free status data - if (PChar(CurrentListEntry^.pkt.data) = STATUS_PACKET) then + if (PChar(CurrentListEntry^.pkt^.data) = STATUS_PACKET) then FreeStatusInfo(CurrentListEntry^.pkt); + // free packet data - {$IF LIBAVFORMAT_VERSION >= 59000000} - if (PChar(CurrentListEntry^.pkt.data) <> STATUS_PACKET) then - av_packet_unref(@CurrentListEntry^.pkt); - {$ELSE} - av_free_packet(@CurrentListEntry^.pkt); - {$ENDIF} - // Note: param must be a pointer to a pointer! - av_freep(@CurrentListEntry); + av_packet_free(@(CurrentListEntry^.pkt)); + + Dispose(CurrentListEntry); CurrentListEntry := TempListEntry; end; LastListEntry := nil; diff --git a/src/media/UVideo.pas b/src/media/UVideo.pas index 2654c8eab..3ce478038 100644 --- a/src/media/UVideo.pas +++ b/src/media/UVideo.pas @@ -796,7 +796,7 @@ function TVideo_FFmpeg.DecodeFrame(): boolean; FrameFinished: Integer; pbIOCtx: PAVIOContext; errnum: integer; - AVPacket: TAVPacket; + AVPacket: PAVPacket; pts: int64; dts: int64; fileSize: int64; @@ -804,6 +804,7 @@ function TVideo_FFmpeg.DecodeFrame(): boolean; begin Result := false; FrameFinished := 0; + AVPacket := nil; if fEOF then Exit; @@ -822,6 +823,8 @@ function TVideo_FFmpeg.DecodeFrame(): boolean; if errnum <> AVERROR(EAGAIN) then Continue; + if (AVPacket = nil) then + AVPacket := av_packet_alloc(); errnum := av_read_frame(fFormatContext, AVPacket); if (errnum < 0) then begin @@ -841,6 +844,7 @@ function TVideo_FFmpeg.DecodeFrame(): boolean; if (urlError <> 0) then begin Log.LogError('Video decoding file error', 'TVideoPlayback_FFmpeg.DecodeFrame'); + av_packet_free(@AVPacket); Exit; end; @@ -856,24 +860,21 @@ function TVideo_FFmpeg.DecodeFrame(): boolean; // error occured, log and exit Log.LogError('Video decoding error: ' + IntToStr(errnum), 'TVideoPlayback_FFmpeg.DecodeFrame'); + av_packet_free(@AVPacket); Exit; end; // if we got a packet from the video stream, then decode it - if (AVPacket.stream_index = fStreamIndex) then + if (AVPacket^.stream_index = fStreamIndex) then begin // decode packet - avcodec_send_packet(fCodecContext, @AVPacket); + avcodec_send_packet(fCodecContext, AVPacket); end; // free the packet from av_read_frame - {$IF LIBAVCODEC_VERSION < 59000000} - av_free_packet( @AVPacket ); - {$ELSE} - av_packet_unref(@AVPacket); - {$ENDIF} + av_packet_free(@AVPacket); end; // reset opaque data and update pts