16

I'm having a hard time, searching how to play a video file from a TMemoryStream (or a similar buffer in memory) using FFMpeg. I've seen many things, including UltraStarDX, expensive FFMpeg components for Delphi and so on.

One component called FFMpeg Vcl Player claims to play video formats from a memory stream. I downloaded the trial version and I guess it uses CircularBuffer.pas for that matter (maybe).

Does any one know how to do this?

Edit: Now the better question is how to play an encrypted video file, using FFMpeg or similar libraries.

Delphi.Boy
  • 1,199
  • 4
  • 17
  • 38
  • Just an idea: could you pass a named pipe to the file-in of FFMPeg? something like `\\.\pipe\NamedPipeToMyData` and then write from the memory stream into the other end as soon as FFMpeg connects. – Stijn Sanders Nov 05 '13 at 10:19
  • @StijnSanders I've also tried named pipes. To be honest, I couldn't get a named pipe to work. Can you point me to some example that creates a named pipe and write something to it? – Delphi.Boy Nov 05 '13 at 10:45
  • 1
    Have a look at this: http://sourceforge.net/p/xxm/code/HEAD/tree/trunk/Delphi/cgi/ xxmCGI is a 'small' exe that pipes the std-in/out to a named pipe, xxmHost 'hosts' the named pipe and handles the requests. – Stijn Sanders Nov 05 '13 at 11:10
  • Correction: xxmCGI connects to xxmHost's named pipe just to get handles for unnamed pipes to forward std-in/out to/from. – Stijn Sanders Nov 05 '13 at 17:14
  • So, is it suitable for my purpose? I need to write contents of a Stream or a buffer. – Delphi.Boy Nov 06 '13 at 06:19
  • 1
    How about playing through VLC? It has Delphi headers and examples are available. – Kromster Jun 04 '14 at 05:50
  • @KromStern, does VLC support playing from a TMemoryStream? – Delphi.Boy Jun 07 '14 at 04:40
  • @Delphi.Boy: Sure, we even used VLC to play live streams from surveillance cameras. – Kromster Jun 07 '14 at 10:23
  • @Delphi.Boy: You might want to accept the answer to this question and start a separate new one about encrypted videos ;) – Kromster Jun 07 '14 at 10:27
  • try this. worked for me https://stackoverflow.com/questions/49023124/extracting-resourcesi-e-mp4-file-from-bpl-packages?noredirect=1#comment85056120_49023124 – shishir ghimire Mar 04 '18 at 06:05

3 Answers3

20

To play video from memory stream, you can use 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..
Roman R.
  • 68,205
  • 6
  • 94
  • 158
pogorskiy
  • 4,705
  • 1
  • 22
  • 21
1

You can waste your time rewriting FFMPEG from C++ to Delphi, or mess with wrapper libraries.

Or if you're just interested in playing a video in Delphi, then check out Mitov's VideoLab components.

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

David Schwartz
  • 1,756
  • 13
  • 18
  • It doesn't seem to support playing from a memory stream, does it? – Delphi.Boy Jun 07 '14 at 04:44
  • what doesn't? If you think about it, most video files are REALLY BIG, and a memory-based stream isn't typically advisable. What kind of video file would only be an in-memory file, with no disk image? Sometimes things aren't supported because they just don't make a whole lot of sense, even though people can certainly come up with odd reasons to do so. – David Schwartz Jun 07 '14 at 05:01
  • 1
    Well, I need to play custom encrypted video files. So, I guessed I could decrypt it to memory and play from there. Is it odd? – Delphi.Boy Jun 07 '14 at 08:18
1

If you want play Stream from memory you can make a virtual memory. I suggest BoxedAppSdk.

This will help you to make a virtual drive with virtual files that you can write on it and then give the virtual path to the player component that you have.

BoxedApp is not free but it is really awesome and very simple in use!

Loghman
  • 1,500
  • 1
  • 14
  • 30