libvlc_media_t的创建
创建libvlc_media_t有两种方法:libvlc_media_new_path()和libvlc_media_new_location()。简单描述一下这两个函数的区别:libvlc_media_new_location()用于打开协议,而libvlc_media_new_path()用于打开文件。因而传递给libvlc_media_new_path()的就是普通的文件路径(绝对路径例如D:\xxx.flv,或者相对路径例如xxx.flv),而传递给libvlc_media_new_location()的就是协议地址(例如“udp://….”,“http://”)。但是这里有一点需要注意,在VLC中“文件”也属于一种广义上的“协议”。因此使用libvlc_media_new_location()也可以打开文件,但是必须在文件路径前面加上“文件协议”的标记“file:///”。例如打开“F:\movie\cuc_ieschool.flv”下的视频,实际使用的代码如下所示。
libvlc_media_new_location (inst, "file:///F:\\movie\\cuc_ieschool.flv");
此外,VLC还支持很多“神奇”的协议,比如输入“screen://”协议就可以进行屏幕录制,代码如下。
libvlc_media_new_location (inst, "screen://");
把libVLC的弹出窗口嵌入到程序中
在这里我只实践过Windows下把libVLC的弹出窗口嵌入到程序中。将窗口或者控件的句柄传递给libvlc_media_player_set_hwnd()函数即可。
这里有一点需要注意,如果把libVLC弹出窗口嵌入到程序中的话,“全屏”功能就不能使用了。
关于libVLC加载的问题
在libVLC中可以通过libvlc_media_player_get_length(),libvlc_video_get_width(),libvlc_video_get_height()等函数获取到视频的时长,宽,高等信息。但是有一个很奇怪的现象:如果在调用完libvlc_media_player_play()之后立即调用上述3个函数的话,返回的值都是0,只有“等待”一段时间(例如调用sleep())后再调用上述函数,才能得到正确的数值。对于这种现象,我觉得可能是libVLC加载完成之后,才能通过上述几个函数获得正确的值(自己推测的,还没有深究)。
/**
* 最简单的基于libVLC的播放器
* Simplest libVLC Player
*
* 雷霄骅 Lei Xiaohua
* 本程序是一个最简单的基于libVLC的视频播放器。
* 适合初学者学习libVLC。
*
* This example is the simplest Video Player based on libVLC.
* Suitable for the beginner of libVLC.
*/
#include <Windows.h>
#include "vlc/vlc.h"
int main(int argc, char* argv[])
{
libvlc_instance_t * inst;
libvlc_media_player_t *mp;
libvlc_media_t *m;
libvlc_time_t length;
int width;
int height;
int wait_time=5000;
//libvlc_time_t length;
/* Load the VLC engine */
inst = libvlc_new (0, NULL);
//Create a new item
//Method 1:
//m = libvlc_media_new_location (inst, "file:///F:\\movie\\cuc_ieschool.flv");
//Screen Capture
//m = libvlc_media_new_location (inst, "screen://");
//Method 2:
m = libvlc_media_new_path (inst, "cuc_ieschool.flv");
/* Create a media player playing environement */
mp = libvlc_media_player_new_from_media (m);
/* No need to keep the media now */
libvlc_media_release (m);
// play the media_player
libvlc_media_player_play (mp);
//wait until the tracks are created
_sleep (wait_time);
length = libvlc_media_player_get_length(mp);
width = libvlc_video_get_width(mp);
height = libvlc_video_get_height(mp);
printf("Stream Duration: %ds\n",length/1000);
printf("Resolution: %d x %d\n",width,height);
//Let it play
_sleep (length-wait_time);
// Stop playing
libvlc_media_player_stop (mp);
// Free the media_player
libvlc_media_player_release (mp);
libvlc_release (inst);
return 0;
}
最简单推流器
/**
* 最简单的基于libVLC的推流器
* Simplest libVLC Streamer
*
* 雷霄骅 Lei Xiaohua
* 本程序是一个最简单的基于libVLC的推流器。
* 适合初学者学习libVLC。
*
* This example is the simplest Streamer based on libVLC.
* Suitable for the beginner of libVLC.
*/
#include <Windows.h>
#include "vlc/vlc.h"
int main(int argc, char **argv) {
libvlc_instance_t *vlc;
const char *url;
//Send File
//Transcode it. Video codec use x264. Audio codec use mpga.
//Mux it to mpegts format.
//And stream it to udp://233.233.233.233:6666
/*
const char *sout = "#transcode{vcodec=h264,fps=25,venc=x264{preset=ultrafast,"\
"profile=main,tune=zerolatency},vb=512,scale=0.5," \
"acodec=mpa,aenc=ffmpeg,ab=64,channels=2}" \
":standard{access=udp,mux=ts,dst=233.233.233.233:6666}";
*/
//Send and playing at same time
const char *sout = "#transcode{vcodec=h264,fps=25,venc=x264{preset=ultrafast,"\
"profile=baseline,tune=zerolatency},vb=512," \
"acodec=mpga,ab=64,channels=2}" \
":duplicate{dst=display,dst=standard{access=udp,mux=ts,dst=233.233.233.233:6666}}";
const char *media_name = "Lei's test";
//Screen Capture
//url = "screen://";
url = "cuc_ieschool.flv";
vlc = libvlc_new(0, NULL);
libvlc_vlm_add_broadcast(vlc, media_name, url, sout, 0, NULL, true, false);
libvlc_vlm_play_media(vlc, media_name);
//play 30s
_sleep(30000);
libvlc_vlm_stop_media(vlc, media_name);
libvlc_vlm_release(vlc);
return 0;
}
播放内存中的流(转) --- 未测试
// Local file/media source.
std::string IMEM_SOURCE_FOLDER = "settings/rvideo/samples/bigdog";
class MyImemData
{
public:
MyImemData() : mFrame(0), mDts(0), mPts(0) {}
~MyImemData() {}
std::vector<cv::Mat> mImages;
std::size_t mFrame;
int64_t mDts;
int64_t mPts;
};
/**
\brief Callback method triggered by VLC to get image data from
a custom memory source. This is used to tell VLC where the
data is and to allocate buffers as needed.
To set this callback, use the "--imem-get=<memory_address>"
option, with memory_address the address of this function in memory.
When using IMEM, be sure to indicate the format for your data
using "--imem-cat=2" where 2 is video. Other options for categories are
0 = Unknown,
1 = Audio,
2 = Video,
3 = Subtitle,
4 = Data
When creating your media instance, use libvlc_media_new_location and
set the location to "imem:/" and then play.
\param[in] data Pointer to user-defined data, this is your data that
you set by passing the "--imem-data=<memory_address>" option when
initializing VLC instance.
\param[in] cookie A user defined string. This works the same way as
data, but for string. You set it by adding the "--imem-cookie=<your_string>"
option when you initialize VLC. Use this when multiple VLC instances are
running.
\param[out] dts The decode timestamp, value is in microseconds. This value
is the time when the frame was decoded/generated. For example, 30 fps
video would be every 33 ms, so values would be 0, 33333, 66666, 99999, etc.
\param[out] pts The presentation timestamp, value is in microseconds. This
value tells the receiver when to present the frame. For example, 30 fps
video would be every 33 ms, so values would be 0, 33333, 66666, 99999, etc.
\param[out] flags Unused,ignore.
\param[out] bufferSize Use this to set the size of the buffer in bytes.
\param[out] buffer Change to point to your encoded frame/audio/video data.
The codec format of the frame is user defined and set using the
"--imem-codec=<four_letter>," where 4 letter is the code for your
codec of your source data.
*/
int MyImemGetCallback (void *data,
const char *cookie,
int64_t *dts,
int64_t *pts,
unsigned *flags,
size_t * bufferSize,
void ** buffer)
{
MyImemData* imem = (MyImemData*)data;
if(imem == NULL)
return 1;
// Loop...
if(imem->mFrame >= imem->mImages.size())
{
imem->mFrame = 0;
}
// Changing this value will impact the playback
// rate on the receiving end (if they use the dts and pts values).
int64_t uS = 33333; // 30 fps
cv::Mat img = imem->mImages[imem->mFrame++];
*bufferSize = img.rows*img.cols*img.channels();
*buffer = img.data;
*dts = *pts = imem->mDts = imem->mPts = imem->mPts + uS;
return 0;
}
/**
\brief Callback method triggered by VLC to release memory allocated
during the GET callback.
To set this callback, use the "--imem-release=<memory_address>"
option, with memory_address the address of this function in memory.
\param[in] data Pointer to user-defined data, this is your data that
you set by passing the "--imem-data=<memory_address>" option when
initializing VLC instance.
\param[in] cookie A user defined string. This works the same way as
data, but for string. You set it by adding the "--imem-cookie=<your_string>"
option when you initialize VLC. Use this when multiple VLC instances are
running.
\param[int] bufferSize The size of the buffer in bytes.
\param[out] buffer Pointer to data you allocated or set during the GET
callback to handle or delete as needed.
*/
int MyImemReleaseCallback (void *data,
const char *cookie,
size_t bufferSize,
void * buffer)
{
// Since I did not allocate any new memory, I don't need
// to delete it here. However, if you did in your get method, you
// should delete/free it here.
return 0;
}
/**
\brief Method to load a series of images to use as raw image data
for the network stream.
\param[in] sourceFolder Path to folder containing jpeg or png images.
*/
std::vector<cv::Mat> GetRawImageData(const std::string& sourceFolder)
{
namespace fs = boost::filesystem;
std::vector<cv::Mat> result;
std::vector<std::string> filenames;
if( fs::exists(sourceFolder) && fs::is_directory(sourceFolder) )
{
for(fs::directory_iterator dir(sourceFolder);
dir != fs::directory_iterator();
dir++)
{
std::string ext = dir->path().extension().string();
if( fs::is_regular_file( dir->status() ) &&
(dir->path().extension() == ".jpeg" ||
dir->path().extension() == ".png") )
{
filenames.push_back(dir->path().string());
}
}
}
if(filenames.size() > 0)
{
// Sort from 0 to N
std::sort(filenames.begin(), filenames.end());
std::vector<std::string>::iterator filename;
for(filename = filenames.begin();
filename != filenames.end();
filename++)
{
cv::Mat img = cv::imread(*filename);
result.push_back(img);
}
}
return result;
}
int main(int argc, char* argv[])
{
// Load images first since we need to know
// the size of the image data for IMEM
MyImemData data;
data.mImages =
GetRawImageData(IMEM_SOURCE_FOLDER);
if(data.mImages.size() == 0)
{
std::cout << "No images found to render/stream.";
return 0;
}
int w, h, channels;
w = data.mImages.front().cols;
h = data.mImages.front().rows;
channels = data.mImages.front().channels();
// You must create an instance of the VLC Library
libvlc_instance_t * vlc;
// You need a player to play media
libvlc_media_player_t *mediaPlayer;
// Media object to play.
libvlc_media_t *media;
// Configure options for this instance of VLC (global settings).
// See VLC command line documentation for options.
std::vector<const char*> options;
std::vector<const char*>::iterator option;
options.push_back("--no-video-title-show");
char imemDataArg[256];
sprintf(imemDataArg, "--imem-data=%#p", &data);
options.push_back(imemDataArg);
char imemGetArg[256];
sprintf(imemGetArg, "--imem-get=%#p", MyImemGetCallback);
options.push_back(imemGetArg);
char imemReleaseArg[256];
sprintf(imemReleaseArg, "--imem-release=%#p", MyImemReleaseCallback);
options.push_back(imemReleaseArg);
options.push_back("--imem-cookie=\"IMEM\"");
// Codec of data in memory for IMEM, raw 3 channel RGB images is RV24
options.push_back("--imem-codec=RV24");
// Video data.
options.push_back("--imem-cat=2");
// If using RAW image data, like RGB24, then you
// must specify the width, height, and number of channels
// to IMEM. Other codes may have that information within
// the data buffer, but RAW will not.
char imemWidthArg[256];
sprintf(imemWidthArg, "--imem-width=%d", w);
options.push_back(imemWidthArg);
char imemHeightArg[256];
sprintf(imemHeightArg, "--imem-height=%d", h);
options.push_back(imemHeightArg);
char imemChannelsArg[256];
sprintf(imemChannelsArg, "--imem-channels=%d", channels);
options.push_back(imemChannelsArg);
//options.push_back("--verbose=2");
// Load the VLC engine
vlc = libvlc_new (int(options.size()), options.data());
// Create a media item from file
media = libvlc_media_new_location (vlc, "imem://");
// Configure any transcoding or streaming
// options for the media source.
options.clear();
// Stream as MPEG2 via RTSP
//options.push_back(":sout=#transcode{venc=ffmpeg{keyint=1,min-keyint=1,tune=zerolatency,bframes=0,vbv-bufsize=1200}, vcodec=mp2v,vb=800}:rtp{sdp=rtsp://:1234/BigDog}");
// Stream as MJPEG (Motion JPEG) to http destination. MJPEG encoder
// does not currently support RTSP
//options.push_back(":sout=#transcode{vcodec=MJPG,vb=800,scale=1,acodec=none}:duplicate{dst=std{access=http,mux=mpjpeg,noaudio,dst=:1234/BigDog.mjpg}");
// Convert to H264 and stream via RTSP
options.push_back(":sout=#transcode{vcodec=h264,venc=x264,vb=0,vbv-bufsize=1200,bframes=0,scale=0,acodec=none}:rtp{sdp=rtsp://:1234/BigDog}");
// Set media options
for(option = options.begin(); option != options.end(); option++)
{
libvlc_media_add_option(media, *option);
}
// Create a media player playing environment
mediaPlayer = libvlc_media_player_new_from_media (media);
// No need to keep the media now
libvlc_media_release (media);
// play the media_player
libvlc_media_player_play (mediaPlayer);
boost::this_thread::sleep(boost::posix_time::milliseconds(60000));
// Stop playing
libvlc_media_player_stop (mediaPlayer);
// Free the media_player
libvlc_media_player_release (mediaPlayer);
// Free vlc
libvlc_release (vlc);
return 0;
}
wiki
1.https://wiki.videolan.org/Hacker_Guide/ 总纲
2.https://wiki.videolan.org/Documentation:Hacker%27s_Guide/Core/#VLC_Pipeline_and_Modularity 基本概念 模块 PIPELINE