我很困难,使用FFMpeg搜索如何从TMemoryStream(或内存中的类似缓冲区)播放视频文件.我看到很多东西,包括UltraStarDX,Delphi等昂贵的FFMpeg组件.
一个名为FFMpeg Vcl Player的组件声称从内存流播放视频格式.我下载了试用版,我猜这是使用CircularBuffer.pas(也许).
有谁知道如何做到这一点?
编辑:
现在更好的问题是如何使用FFMpeg或类似的库来播放加密的视频文件.
解决方法
要从内存流播放视频,您可以使用自定义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_,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);
- if (err < 0)
- return -1;
- //// normal usage of ctx
- //// avformat_find_stream_info(ctx,NULL);
- //// av_read_frame(ctx,&pkt);
- //// etc..