【问题标题】:Play a Video from MemoryStream, Using FFMpeg使用 FFMpeg 从 MemoryStream 播放视频
【发布时间】:2013-11-05 09:10:36
【问题描述】:

我很难搜索如何使用 FFMpeg 从 TMemoryStream(或内存中的类似缓冲区)播放视频文件。我见过很多东西,包括 UltraStarDX、用于 Delphi 的昂贵的 FFMpeg 组件等等。

一个名为FFMpeg Vcl Player 的组件声称可以从内存流中播放视频格式。我下载了试用版,我猜它使用 CircularBuffer.pas (也许)。

有人知道怎么做吗?

编辑: 现在更好的问题是如何使用 FFMpeg 或类似库播放加密的视频文件。

【问题讨论】:

  • 只是一个想法:你能将命名管道传递给 FFMPeg 的文件输入吗? \\.\pipe\NamedPipeToMyData 之类的东西,然后在 FFMpeg 连接后立即从内存流写入另一端。
  • @StijnSanders 我也尝试过命名管道。老实说,我无法让命名管道工作。您能指出一些创建命名管道并向其写入内容的示例吗?
  • 看看这个:sourceforge.net/p/xxm/code/HEAD/tree/trunk/Delphi/cgi xxmCGI 是一个“小型”exe,它将标准输入/输出通过管道传输到命名管道,xxmHost“托管”命名管道并处理请求。
  • 更正:xxmCGI 连接到 xxmHost 的命名管道只是为了获取未命名管道的句柄以将标准输入/输出转发到/从。
  • 用VLC玩怎么样?它有 Delphi 头文件和示例。

标签: delphi ffmpeg


【解决方案1】:

要播放内存流中的视频,您可以使用自定义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..

【讨论】:

  • 好吧,我用的是 Delphi,你已经发布了 CPP。你能提供更多细节吗?
  • 您能提供更多信息吗?
  • 投反对票,问题是关于 Delphi,而不是 C++。
  • 在 C++ 中使用当前 API 时,这对我也不起作用。
  • 与FFmpeg.AutoGen 配合得很好,我确实将您的代码重写为 C#。谢谢!
【解决方案2】:

您可能会浪费时间将 FFMPEG 从 C++ 重写为 Delphi,或者弄乱包装库。

或者,如果您只是对在 Delphi 中播放视频感兴趣,请查看 Mitov 的 VideoLab 组件。

http://www.mitov.com/products/videolab#components

【讨论】:

  • 它似乎不支持从内存流播放,是吗?
  • 什么不是?如果您考虑一下,大多数视频文件都非常大,通常不建议使用基于内存的流。什么样的视频文件只能是内存文件,没有磁盘映像?有时不支持某些事情是因为它们没有多大意义,即使人们肯定会想出奇怪的理由这样做。
  • 好吧,我需要播放自定义加密视频文件。所以,我猜我可以将它解密到内存中并从那里播放。很奇怪吗?
【解决方案3】:

如果你想从内存中播放 Stream,你可以创建一个虚拟内存。我建议BoxedAppSdk。

这将帮助您创建一个虚拟驱动器,其中包含可以写入的虚拟文件,然后提供您拥有的播放器组件的虚拟路径。

BoxedApp 不是免费的,但它真的很棒而且使用起来非常简单!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-14
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    相关资源
    最近更新 更多