aboutsummaryrefslogtreecommitdiffstats
path: root/cmake/src/media/UMediaCore_FFmpeg.pas
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/src/media/UMediaCore_FFmpeg.pas')
-rw-r--r--cmake/src/media/UMediaCore_FFmpeg.pas146
1 files changed, 143 insertions, 3 deletions
diff --git a/cmake/src/media/UMediaCore_FFmpeg.pas b/cmake/src/media/UMediaCore_FFmpeg.pas
index 9ad19a5b..2d572ff2 100644
--- a/cmake/src/media/UMediaCore_FFmpeg.pas
+++ b/cmake/src/media/UMediaCore_FFmpeg.pas
@@ -34,12 +34,16 @@ interface
{$I switches.inc}
uses
- UMusic,
+ Classes,
+ ctypes,
+ sdl,
avcodec,
avformat,
avutil,
+ avio,
+ UMusic,
ULog,
- sdl;
+ UPath;
type
PPacketQueue = ^TPacketQueue;
@@ -95,7 +99,24 @@ type
implementation
uses
- SysUtils;
+ SysUtils,
+ UConfig;
+
+function FFmpegStreamOpen(h: PURLContext; filename: PChar; flags: cint): cint; cdecl; forward;
+function FFmpegStreamRead(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl; forward;
+function FFmpegStreamWrite(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl; forward;
+function FFmpegStreamSeek(h: PURLContext; pos: int64; whence: cint): int64; cdecl; forward;
+function FFmpegStreamClose(h: PURLContext): cint; cdecl; forward;
+
+const
+ UTF8FileProtocol: TURLProtocol = (
+ name: 'ufile';
+ url_open: FFmpegStreamOpen;
+ url_read: FFmpegStreamRead;
+ url_write: FFmpegStreamWrite;
+ url_seek: FFmpegStreamSeek;
+ url_close: FFmpegStreamClose;
+ );
var
Instance: TMediaCore_FFmpeg;
@@ -103,6 +124,7 @@ var
constructor TMediaCore_FFmpeg.Create();
begin
inherited;
+ av_register_protocol(@UTF8FileProtocol);
AVCodecLock := SDL_CreateMutex();
end;
@@ -163,6 +185,7 @@ begin
begin
Stream := FormatCtx.streams[i];
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
if (Stream.codec.codec_type = CODEC_TYPE_VIDEO) and
(FirstVideoStream < 0) then
begin
@@ -175,6 +198,20 @@ begin
FirstAudioStream := i;
end;
end;
+{$ELSE}
+ if (Stream.codec.codec_type = AVMEDIA_TYPE_VIDEO) and
+ (FirstVideoStream < 0) then
+ begin
+ FirstVideoStream := i;
+ end;
+
+ if (Stream.codec.codec_type = AVMEDIA_TYPE_AUDIO) and
+ (FirstAudioStream < 0) then
+ begin
+ FirstAudioStream := i;
+ end;
+ end;
+{$IFEND}
// return true if either an audio- or video-stream was found
Result := (FirstAudioStream > -1) or
@@ -194,7 +231,11 @@ begin
begin
Stream := FormatCtx^.streams[i];
+{$IF LIBAVCODEC_VERSION < 52064000} // < 52.64.0
if (Stream.codec^.codec_type = CODEC_TYPE_AUDIO) then
+{$ELSE}
+ if (Stream.codec^.codec_type = AVMEDIA_TYPE_AUDIO) then
+{$IFEND}
begin
StreamIndex := i;
Break;
@@ -220,6 +261,105 @@ begin
Result := true;
end;
+
+{**
+ * UTF-8 Filename wrapper based on:
+ * http://www.mail-archive.com/libav-user@mplayerhq.hu/msg02460.html
+ *}
+
+function FFmpegStreamOpen(h: PURLContext; filename: PChar; flags: cint): cint; cdecl;
+var
+ Stream: TStream;
+ Mode: word;
+ ProtPrefix: string;
+ FilePath: IPath;
+begin
+ // check for protocol prefix ('ufile:') and strip it
+ ProtPrefix := Format('%s:', [UTF8FileProtocol.name]);
+ if (StrLComp(filename, PChar(ProtPrefix), Length(ProtPrefix)) = 0) then
+ begin
+ Inc(filename, Length(ProtPrefix));
+ end;
+
+ FilePath := Path(filename);
+
+ if ((flags and URL_RDWR) <> 0) then
+ Mode := fmCreate
+ else if ((flags and URL_WRONLY) <> 0) then
+ Mode := fmCreate // TODO: fmCreate is Read+Write -> reopen with fmOpenWrite
+ else
+ Mode := fmOpenRead or fmShareDenyWrite;
+
+ Result := 0;
+
+ try
+ Stream := TBinaryFileStream.Create(FilePath, Mode);
+ h.priv_data := Stream;
+ except
+ Result := AVERROR_NOENT;
+ end;
+end;
+
+function FFmpegStreamRead(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+var
+ Stream: TStream;
+begin
+ Stream := TStream(h.priv_data);
+ if (Stream = nil) then
+ raise EInvalidContainer.Create('FFmpegStreamRead on nil');
+ try
+ Result := Stream.Read(buf[0], size);
+ except
+ Result := -1;
+ end;
+end;
+
+function FFmpegStreamWrite(h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+var
+ Stream: TStream;
+begin
+ Stream := TStream(h.priv_data);
+ if (Stream = nil) then
+ raise EInvalidContainer.Create('FFmpegStreamWrite on nil');
+ try
+ Result := Stream.Write(buf[0], size);
+ except
+ Result := -1;
+ end;
+end;
+
+function FFmpegStreamSeek(h: PURLContext; pos: int64; whence: cint): int64; cdecl;
+var
+ Stream : TStream;
+ Origin : TSeekOrigin;
+begin
+ Stream := TStream(h.priv_data);
+ if (Stream = nil) then
+ raise EInvalidContainer.Create('FFmpegStreamSeek on nil');
+ case whence of
+ 0 {SEEK_SET}: Origin := soBeginning;
+ 1 {SEEK_CUR}: Origin := soCurrent;
+ 2 {SEEK_END}: Origin := soEnd;
+ AVSEEK_SIZE: begin
+ Result := Stream.Size;
+ Exit;
+ end
+ else
+ Origin := soBeginning;
+ end;
+ Result := Stream.Seek(pos, Origin);
+end;
+
+function FFmpegStreamClose(h: PURLContext): cint; cdecl;
+var
+ Stream : TStream;
+begin
+ Stream := TStream(h.priv_data);
+ Stream.Free;
+ Result := 0;
+end;
+
+
{ TPacketQueue }
constructor TPacketQueue.Create();