XDemux.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #pragma once #include "xformat.h" class XDemux : public XFormat { public: static AVFormatContext *Open(const char *url);
bool Read(AVPacket *pkt);
bool Seek(long long pts, int stream_index); };
|
XDemux.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| #include "xdemux.h" #include <iostream> #include <thread> #include "xtools.h"
using namespace std;
extern "C" { #include <libavformat\avformat.h> }
static void PrintErr(int err) { char buf[1024] = { 0 }; av_strerror(err, buf, sizeof(buf) - 1); cerr << buf << endl; } #define BERR(err) if(err != 0) {PrintErr(err); return 0;}
AVFormatContext *XDemux::Open(const char *url) { AVFormatContext *c = nullptr; AVDictionary *opts = nullptr;
av_dict_set(&opts, "stimeout", "1000000", 0); auto re = avformat_open_input(&c, url, nullptr, &opts); if (opts) av_dict_free(&opts);
BERR(re);
re = avformat_find_stream_info(c, nullptr); BERR(re); av_dump_format(c, 0, url, 0);
return c; }
bool XDemux::Read(AVPacket *pkt) { unique_lock<mutex> lock(mux_); if (!c_) return false;
auto re = av_read_frame(c_, pkt); BERR(re);
last_time_ = NowMs();
return true; }
bool XDemux::Seek(long long pts, int stream_index) { unique_lock<mutex> lock(mux_); if (!c_) return false;
auto re = av_seek_frame(c_, stream_index, pts, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD); BERR(re);
return true; }
|
Open()
作用:通过 Open
方法,XDemux
类能够打开指定 URL 的多路复用器上下文,设置连接选项,获取媒体信息,并打印封装信息。该方法封装了多路复用器上下文的打开、选项设置和错误处理步骤,确保操作的可靠性和可调试性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| AVFormatContext *XDemux::Open(const char *url) { AVFormatContext *c = nullptr; AVDictionary *opts = nullptr;
av_dict_set(&opts, "stimeout", "1000000", 0); auto re = avformat_open_input(&c, url, nullptr, &opts);
if (opts) av_dict_free(&opts);
BERR(re);
re = avformat_find_stream_info(c, nullptr); BERR(re); av_dump_format(c, 0, url, 0);
return c; }
|
Read()
作用:通过 Read
方法,XDemux
类能够从多路复用器中读取一帧数据并存储在提供的 AVPacket
对象中。该方法通过线程安全的资源访问、错误处理和时间戳记录,确保读取操作的可靠性和可调试性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| bool XDemux::Read(AVPacket *pkt) { unique_lock<mutex> lock(mux_); if (!c_) return false;
auto re = av_read_frame(c_, pkt); BERR(re);
last_time_ = NowMs();
return true; }
|
Seek()
作用:这个方法通常用于在打开的多路复用器中进行时间跳转,例如在视频播放器中用户拖动进度条时调用。在实际应用中,可以在一个循环中调用 Seek
方法,定位到指定位置并读取相应的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| bool XDemux::Seek(long long pts, int stream_index) { unique_lock<mutex> lock(mux_); if (!c_) return false;
auto re = av_seek_frame(c_, stream_index, pts, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD); BERR(re);
return true; }
|