我很难搜索如何使用 FFMpeg 从 TMemoryStream (或内存中的类似缓冲区)播放视频文件。我见过很多东西,包括 UltraStarDX、Delphi 的昂贵的 FFMpeg 组件等等。
一个名为FFMpeg Vcl Player的组件声称可以从内存流中播放视频格式。我下载了试用版,我猜它使用 CircularBuffer.pas (也许)。
有谁知道如何做到这一点?
编辑:现在更好的问题是如何使用 FFMpeg 或类似库播放加密的视频文件。
我很难搜索如何使用 FFMpeg 从 TMemoryStream (或内存中的类似缓冲区)播放视频文件。我见过很多东西,包括 UltraStarDX、Delphi 的昂贵的 FFMpeg 组件等等。
一个名为FFMpeg Vcl Player的组件声称可以从内存流中播放视频格式。我下载了试用版,我猜它使用 CircularBuffer.pas (也许)。
有谁知道如何做到这一点?
编辑:现在更好的问题是如何使用 FFMpeg 或类似库播放加密的视频文件。
要从内存流中播放视频,您可以使用 custom AVIOContext
。
static const int kBufferSize = 4 * 1024;
class my_iocontext_private
{
private:
my_iocontext_private(my_iocontext_private const &);
my_iocontext_private& operator = (my_iocontext_private const &);
public:
my_iocontext_private(IInputStreamPtr inputStream)
: inputStream_(inputStream)
, buffer_size_(kBufferSize)
, buffer_(static_cast<unsigned char*>(::av_malloc(buffer_size_))) {
ctx_ = ::avio_alloc_context(buffer_, buffer_size_, 0, this,
&my_iocontext_private::read, NULL, &my_iocontext_private::seek);
}
~my_iocontext_private() {
::av_free(ctx_);
::av_free(buffer_);
}
void reset_inner_context() { ctx_ = NULL; buffer_ = NULL; }
static int read(void *opaque, unsigned char *buf, int buf_size) {
my_iocontext_private* h = static_cast<my_iocontext_private*>(opaque);
return h->inputStream_->Read(buf, buf_size);
}
static int64_t seek(void *opaque, int64_t offset, int whence) {
my_iocontext_private* h = static_cast<my_iocontext_private*>(opaque);
if (0x10000 == whence)
return h->inputStream_->Size();
return h->inputStream_->Seek(offset, whence);
}
::AVIOContext *get_avio() { return ctx_; }
private:
IInputStreamPtr inputStream_; // abstract stream interface, You can adapt it to TMemoryStream
int buffer_size_;
unsigned char * buffer_;
::AVIOContext * ctx_;
};
//// ..........
/// prepare input stream:
IInputStreamPtr inputStream = MyCustomCreateInputStreamFromMemory();
my_iocontext_private priv_ctx(inputStream);
AVFormatContext * ctx = ::avformat_alloc_context();
ctx->pb = priv_ctx.get_avio();
int err = avformat_open_input(&ctx, "arbitrarytext", NULL, NULL);
if (err < 0)
return -1;
//// normal usage of ctx
//// avformat_find_stream_info(ctx, NULL);
//// av_read_frame(ctx, &pkt);
//// etc..
如果你想从内存中播放 Stream,你可以创建一个虚拟内存。我建议BoxedAppSdk。
这将帮助您使用可以在其上写入的虚拟文件创建一个虚拟驱动器,然后为您拥有的播放器组件提供虚拟路径。
BoxedApp不是免费的,但它真的很棒而且使用起来非常简单!
您可能会浪费时间将 FFMPEG 从 C++ 重写为 Delphi,或者弄乱包装库。
或者,如果您只是对在 Delphi 中播放视频感兴趣,请查看 Mitov 的 VideoLab 组件。