XDecodeTask.h
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
| #pragma once #include "xtools.h" #include "xdecode.h" #include "xcodec.h"
class XDecodeTask : public XThread { public: bool Open(AVCodecParameters *para);
void Do(AVPacket *pkt) override; void Main() override;
AVFrame *GetFrame(); private: std::mutex mux_; XDecode decode_; XAVPacketList pkt_list_; AVFrame *frame_ = nullptr; bool need_view_ = false; };
|
参数说明:
1 2 3 4 5 6
| private: std::mutex mux_; XDecode decode_; XAVPacketList pkt_list_; AVFrame *frame_ = nullptr; bool need_view_ = false;
|
XDecodeTask.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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| #include "xdecodeTask.h" #include <iostream>
extern "C" { #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> }
using namespace std;
bool XDecodeTask::Open(AVCodecParameters *para) { if (!para) { LOGERROR("para is null !!"); return false; } unique_lock<mutex> lock(mux_); auto c = decode_.Create(para->codec_id, false); if (!c) { LOGERROR("decode_.Create failed!"); return false; }
avcodec_parameters_to_context(c, para); decode_.set_c(c); if (!decode_.Open()) { LOGERROR("decode_.Open failed!"); return false; } LOGINFO("Open decode success!");
return true; }
void XDecodeTask::Do(AVPacket *pkt) { cout << "#" << flush;
if (!pkt || pkt->stream_index != 0) { return; }
pkt_list_.Push(pkt); }
AVFrame *XDecodeTask::GetFrame() { unique_lock<mutex> lock(mux_); if (!need_view_ || !frame_ || !frame_->buf[0]) return nullptr;
auto f = av_frame_alloc(); auto re = av_frame_ref(f, frame_); if (re != 0) { PrintErr(re); av_frame_free(&f); return nullptr; } need_view_ = false; return f; }
void XDecodeTask::Main() { { unique_lock<mutex> lock(mux_); if (!frame_) frame_ = av_frame_alloc(); } while (!is_exit_) { auto pkt = pkt_list_.Pop(); if (!pkt) { this_thread::sleep_for(1ms); continue; }
bool re = decode_.Send(pkt); av_packet_free(&pkt); if (!re) { this_thread::sleep_for(1ms); continue; }
{ unique_lock<mutex> lock(mux_); if (decode_.Recv(frame_)) { cout << "@" << flush; need_view_ = true; } } this_thread::sleep_for(1ms); }
{ unique_lock<mutex> lock(mux_); if (frame_) av_frame_free(&frame_); } }
|
Open()
作用:初始化视频解码器。
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
| bool XDecodeTask::Open(AVCodecParameters *para) { if (!para) { LOGERROR("para is null !!"); return false; } unique_lock<mutex> lock(mux_); auto c = decode_.Create(para->codec_id, false); if (!c) { LOGERROR("decode_.Create failed!"); return false; } avcodec_parameters_to_context(c, para); decode_.set_c(c); if (!decode_.Open()) { LOGERROR("decode_.Open failed!"); return false; } LOGINFO("Open decode success!");
return true; }
|
Do()
责任链处理函数
作用:该方法用于接收音视频数据包,并将符合条件的数据包存入一个线程安全的列表中。
1 2 3 4 5 6 7 8 9 10 11
| void XDecodeTask::Do(AVPacket *pkt) { cout << "#" << flush;
if (!pkt || pkt->stream_index != 0) { return; }
pkt_list_.Push(pkt); }
|
GetFrame()
作用:用于获取当前解码的帧(AVFrame
)
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
| AVFrame *XDecodeTask::GetFrame() { unique_lock<mutex> lock(mux_);
if (!need_view_ || !frame_ || !frame_->buf[0]) return nullptr;
auto f = av_frame_alloc(); auto re = av_frame_ref(f, frame_); if (re != 0) { PrintErr(re); av_frame_free(&f); return nullptr; } need_view_ = false; return f; }
|
Main()
作用:用于在一个独立的线程中持续接收音视频数据包,将其解码为帧,并在需要时标记为需要渲染。
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
| void XDecodeTask::Main() { { unique_lock<mutex> lock(mux_); if (!frame_) frame_ = av_frame_alloc(); } while (!is_exit_) { auto pkt = pkt_list_.Pop(); if (!pkt) { this_thread::sleep_for(1ms); continue; }
bool re = decode_.Send(pkt); av_packet_free(&pkt); if (!re) { this_thread::sleep_for(1ms); continue; }
{ unique_lock<mutex> lock(mux_); if (decode_.Recv(frame_)) { cout << "@" << flush; need_view_ = true; } } this_thread::sleep_for(1ms); }
{ unique_lock<mutex> lock(mux_); if (frame_) av_frame_free(&frame_); } }
|