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 * leixiaohua1020@126.com * 中國傳媒大學/數字電視技術 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程序是一個最簡單的基於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 * leixiaohua1020@126.com * 中國傳媒大學/數字電視技術 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * 本程序是一個最簡單的基於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