15

FFMpeg を使用して TMemoryStream (またはメモリ内の同様のバッファ) からビデオ ファイルを再生する方法を探すのに苦労しています。UltraStarDX、Delphi 用の高価な FFMpeg コンポーネントなど、多くのものを見てきました。

FFMpeg Vcl Playerと呼ばれる 1 つのコンポーネントは、メモリ ストリームからビデオ フォーマットを再生すると主張しています。試用版をダウンロードしましたが、そのために CircularBuffer.pas を使用していると思います (おそらく)。

これを行う方法を知っている人はいますか?

編集:FFMpegまたは同様のライブラリを使用して、暗号化されたビデオファイルを再生する方法がより良い質問です。

4

3 に答える 3

19

メモリ ストリームからビデオを再生するには、 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..
于 2013-12-16T12:04:41.940 に答える
1

ストリームをメモリから再生したい場合は、仮想メモリを作成できます。BoxedAppSdkをお勧めします。

これは、書き込み可能な仮想ファイルを含む仮想ドライブを作成し、プレイヤー コンポーネントへの仮想パスを与えるのに役立ちます。

BoxedAppは無料ではありませんが、本当に素晴らしく、使い方はとても簡単です!

于 2014-06-03T06:47:56.050 に答える
1

FFMPEG を C++ から Delphi に書き換えたり、ラッパー ライブラリをいじったりして時間を無駄にする可能性があります。

または、Delphi でビデオを再生することに興味がある場合は、Mitov の VideoLab コンポーネントを調べてください。

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

于 2014-06-02T23:36:50.193 に答える