First of all I'll say I'm new to the VLC world (so go easy on me )
I'm trying to use the libvlc_media_new_callbacks API to open a video file (.mov file to be specific) from memory buffer and play it.
I think my problem is to pass the VLC the right video parameters (format, fps,...) so it could open and read the file correctly.
I tried to look for an example online of something like my case but couldn't find anything.
Properties of the file I'm trying to play:
* Format: HEVC
* Width: 1920 pixels
* Height: 960 pixels
* Frame rate: 25 fps
Tnx
This is my code:
Code: Select all
[using namespace std;
#include <vlc/vlc.h>
#include <memory>
#include <cstring>
#include <unistd.h>
#include <vector>
#include <iostream>
#include <fstream>
#define WIDTH 1920 // 1080
#define HEIGHT 960 // 720
class MemVideoData
{
public:
MemVideoData(char *data, int data_bytes) : video(data), bytes(data_bytes) { } //init
~MemVideoData() {}
char* video; // pointer to video in memory
size_t bytes;
size_t pos = 0;
};
ssize_t media_read_cb(void *opaque, unsigned char* buf, size_t len)
{
MemVideoData *mVid = (MemVideoData*) opaque; //cast and give context
size_t copyLen = std::min(mVid->bytes - mVid->pos, len);
char *start = mVid->video + mVid->pos;
memcpy(buf,start, copyLen); //copy bytes requested to buffer.
mVid->pos += (copyLen % mVid->bytes);
return copyLen;
}
int media_open_cb(void* opaque, void** datap, uint64_t* sizep)
{
//cast opaque to our video state struct
MemVideoData *mVid = static_cast<MemVideoData*> (opaque);
*sizep = UINT64_MAX; //set stream length
*datap = mVid;
return 0;
}
int media_seek_cb(void *opaque, uint64_t offset)
{
return 0;
}
void media_close_cb(void *opaque)
{
}
// load a file to memory, write address into "fileInRam"
int loadFileToMem(const char* filePath, char** fileInRam)
{
int bytes = 0;
FILE *file=fopen(filePath,"r");
if(NULL == file)
{
return -1;
}
fseek(file,0L,SEEK_END); //seek to end
bytes = ftell(file); // record size in bytes
*fileInRam = new char[bytes]; //allocate ram
if(NULL == *fileInRam)
{
return -2;
}
fread(fileInRam,sizeof(unsigned char), bytes, file); //read file into ram
fclose(file); //close file
return bytes;
}
int main()
{
int imgSize = HEIGHT*WIDTH*3;
char* filePath = (char*)"/usr2/damrani/Downloads/video-h265.mkv";
char* ramBuff;
int bytes = loadFileToMem(filePath,&ramBuff); //load file into byte (char) vector
if(-1 == bytes)
{
cout << "Could not open file !" << endl;
return -1;
}
else if(-2 == bytes)
{
cout << "Could not allocate memory! " << endl;
return -1;
}
else if(0 == bytes)
{
cout << "File length 0 bytes! " << endl ;
return -1;
}
cout << "Loaded file to memory address: " << std::hex << static_cast<void*>(ramBuff) << endl;
cout << "Bytes: " << std::dec << bytes << endl;
MemVideoData mem(ramBuff, imgSize);// = new MemVideoData(data, imgSize);
libvlc_instance_t *vlc;
// add Verbose option to instance
std::vector<const char*> options;
options.push_back("--verbose=4");
vlc = libvlc_new (int(options.size()), options.data());
libvlc_media_t* media = libvlc_media_new_callbacks(vlc,media_open_cb, media_read_cb, media_seek_cb, media_close_cb, (void*)&mem);
// Add the streaming string given by the vlc app
//libvlc_media_add_option(media, ":sout=#transcode{vcodec=h264,venc=x264,vb=0,vbv-bufsize=1200,bframes=0,scale=0,acodec=none}:rtp{dst=localhost, port=9555, name=test, mux=ts,sap}");
libvlc_media_add_option(media, ":demux=rawvid");
libvlc_media_add_option(media, ":rawvid-fps=25");
libvlc_media_add_option(media, ":rawvid-height=960");
libvlc_media_add_option(media, ":rawvid-width=1920");
libvlc_media_add_option(media, ":rawvid-chroma=RV32"); //24bit RGB
// Create a media player playing environment
libvlc_media_player_t *mediaPlayer = libvlc_media_player_new_from_media (media);
// play the media_player
libvlc_media_player_play (mediaPlayer);
sleep(15);
// Stop playing
libvlc_media_player_stop (mediaPlayer);
// Free the media_player
libvlc_media_player_release (mediaPlayer);
// Free vlc
libvlc_release (vlc);
}]