当前位置:网站首页>Player actual combat 16 xdecode class
Player actual combat 16 xdecode class
2022-06-12 14:09:00 【Sister Suo】
1.xdecode.h
class xdecode
{
public:
bool isAudio=false;
//pa After the parameters pointing to the space are passed to the decoder, the data in this space is useless , Need to free up this space , Failure to free will result in memory leaks ,
// Release before all returns of this function ( Both success and error need to be released )
virtual bool open(AVCodecParameters* pa);
virtual void close();
virtual void clear();
// take packet Send to decoding buffer queue , And empty pkt Space ( Objects and media content )
virtual bool send(AVPacket*pkt);
// Receive the decoded frame in the decoding buffer queue , once send Corresponding multiple times receive,send When it's over, I have to receive Make sure you empty
virtual AVFrame* receive(int&r);
protected:
AVCodecContext* codeccontext = 0;
std::mutex mux;
};
and demux Similar to class , take mux The lock and context variables are set to protected
2.main How to use... In functions
xdecode vdecode;
cout << "vdecode.open()" << vdecode.open(demux.CopyVPara()) << endl;
xdecode adecode;
cout << "adecode.open()" << adecode.open(demux.CopyAPara()) << endl;
int i = 0;
for (;;)
{
AVPacket* pkt = demux.readfz();// After reading one packet Automatically read the next
if (vdecode.isAudio == false)
{
cout<<"send"<<vdecode.send(pkt)<<endl;
for (;;)
{
int re = 0;
AVFrame* frame = vdecode.receive(re);
if (re != 0)break;
}
}
if (adecode.isAudio == true)
{
cout << "send" << adecode.send(pkt) << endl;
for (;;)
{
int re = 0;
AVFrame* frame = adecode.receive(re);
if (re != 0)break;
}
}
if (!pkt)break;
}
Audio and video unpacking use the same class , Decode the various classes used , So two are instantiated decode, Take the video decoder as an example :
01. First instantiation :xdecode vdecode;
02. Then make a copy of the video parameters obtained by unpacking , Pass as a parameter to vdecode:vdecode.open(demux.CopyVPara()) << endl;
03. Read and package in the result of unpacking , Read one by one packet, The result is put in pkt in :AVPacket* pkt = demux.readfz();
04. What will be read out pkt Send it to the newly instantiated decoder vdecode decode :vdecode.send(pkt)
05. Put the result of the decoding thread in frame in :AVFrame* frame = vdecode.receive(re);
3.xdecode.cpp
bool xdecode::open(AVCodecParameters* pa)
{
// Fault tolerant processing
if (!pa)return false;//pa It's empty , Return error
close();
if (pa->codec_type == 1)
isAudio = true;
else
isAudio = false;
if(isAudio)
const AVCodec* codec = avcodec_find_decoder(pa->codec_id);
// The decoder number in the stream may not be found , Here we need to make a judgment to see if we can find the decoder
if (!codec)
{
avcodec_parameters_free(&pa);
std::cout << "can't find the codec id" <<pa->codec_id << endl;
return false;
}
if (!isAudio)
std::cout << " find the video codec id" << pa->codec_id << endl;
else
std::cout << " find the audio codec id" << pa->codec_id << endl;
mux.lock();
///03 Create decoder context
codeccontext = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codeccontext, pa);// The information obtained by unpacking is passed to the decoding context
avcodec_parameters_free(&pa);
// Eight thread decoding
codeccontext->thread_count = 8;
///05 Open decoder context
int re = avcodec_open2(codeccontext, 0, 0);// The second parameter is the decoder codec, But it has been passed in when creating the context , There is no need to pass it here
if (re != 0)
{
avcodec_parameters_free(&pa);
mux.unlock();
char buf[1024] = {
0 };
av_strerror(re, buf, sizeof(buf) - 1);// use buf Store error messages
std::cout << "open audio codec failed!" << buf << endl;
getchar();
return false;
}
std::cout << "video codec success!" << endl;
mux.unlock();
return true;
}
01. According to what was passed in codec_id Know what kind of decoder it is , According to this id No. find the corresponding decoder :
const AVCodec* codec = avcodec_find_decoder(pa->codec_id);
02. Pass a pointer to the video decoder into , Make room for the decoder context members of the class , And set the default parameters :
codeccontext = avcodec_alloc_context3(codec);
03. The unpacked information is passed to the decoder context , So far, unpacking the context has completed his mission , Can be released :avcodec_parameters_to_context(codeccontext, pa);
avcodec_parameters_free(&pa);
04. Open decoder context , The second parameter is the decoder codec, But it has been passed in when creating the context , There is no need to pass it here :
int re = avcodec_open2(codeccontext, 0, 0);
void xdecode::close()
{
mux.lock();
if (codeccontext)
{
avcodec_close(codeccontext);// Used in other functions codec All code snippets must be locked
avcodec_free_context(&codeccontext);
}
mux.unlock();
}
Decoder context codeccontext For out of class inaccessible , There will be close The function is encapsulated into a function
void xdecode::clear()// Clear the decoding buffer , Larger than the read buffer
{
mux.lock();
if (codeccontext)
avcodec_flush_buffers(codeccontext);
mux.unlock();
}
The data members in the class are closed and cleaned up codeccontext
bool xdecode::send(AVPacket* pkt)
{
if (!pkt || pkt->size <= 0 || !pkt->data)
{
cout << "a" << endl;
return false;
}
mux.lock();
if(!codeccontext)
{
mux.unlock();
cout << "b" << endl;
return false;
}
int re = avcodec_send_packet(codeccontext, pkt);// take pkt For the one opened in front codec
mux.unlock();
av_packet_free(&pkt);
if (re != 0)
{
cout << "c" << endl;
return false;
}
return true;
}
take pkt For the one opened in front codec:
int re = avcodec_send_packet(codeccontext, pkt);
AVFrame* xdecode::receive(int&r)
{
mux.lock();
if (!codeccontext)
{
mux.unlock();
return NULL;
}
AVFrame* frame = av_frame_alloc();// Open up space for receiving decoding queue output
r = avcodec_receive_frame(codeccontext, frame);
mux.unlock();
if (r != 0)
{
av_frame_free(&frame);// If the reception fails, the reception space will be opened in vain , To empty
return NULL;
}
cout <<"["<< frame->linesize[0]<<"]" << flush;
return frame;
}
01 Open up space for receiving decoding queue output :AVFrame* frame = av_frame_alloc();
02 Get... According to the decoder context frame:
r = avcodec_receive_frame(codeccontext, frame);
If the fault-tolerant interpretation fails , Is open up frame The space is useless , It needs to be emptied
4. result
Use flv File to test :
According to the printed a and c, There are two problems :
01. Read from unpacking packet There is a problem :
AVPacket* pkt = demux.readfz();
02 take pkt For the one opened in front codec failed :
int re = avcodec_send_packet(codeccontext, pkt);
What you see on the Internet and knowledge supplement :
Directly construct one of the key parameters obtained from the known information of the input stream AVCodecParameters, After such construction, it can also be decoded normally , But the decoded input stream has very strict restrictions :
Input pkt in data The data must be in 00 00 00 01 Initial data , such as ps flow rtsp rtp Data can be decoded normally , But if the open stream is flv MP4 When you wait, something goes wrong :No start code is found, Or keep returning AVERROR(EAGAIN)
NAL Full name Network Abstract Layer, Network abstraction layer .
(https://blog.csdn.net/ygm_linux/article/details/25562921)
stay H.264/AVC Video coding standard , The whole system framework is divided into two levels : Video coding level (VCL) And network abstraction (NAL). among , The former is responsible for effectively representing the content of video data , The latter is responsible for formatting the data and providing header information , To ensure that data is suitable for transmission on various channels and storage media . So every frame of data is one NAL unit (SPS And PPS With the exception of ). In practice H264 In data frame , Often the frame is preceded by 00 00 00 01 or 00 00 01 Separator , Generally speaking, the first frame data compiled by the encoder is PPS And SPS, Then for I frame ……
Here's the picture :
NALU Type is a sharp tool for us to judge the type of frame , From the official documents, as shown in the figure below :
With 00 00 00 01 The next byte after segmentation is NALU type , After converting it to binary data , The order of interpretation is from left to right , as follows :
(1) The first 1 A bit forbids a bit , The value is 1 There is a syntax error
(2) The first 2~3 Bit is the reference level
(3) The first 4~8 be for the purpose of nal Unit type
Such as the above 00000001 After the 67,68 as well as 65
among 0x67 The binary code of is :
0110 0111
4-8 by 00111, To decimal 7, Refer to the second picture :7 Corresponding sequence parameter set SPS, namely 0x67 Start until the next 00000001 The data between is SPS

Finally, it was changed , The problem is main Function , You should not judge the type in the decoder , Instead, it should be judged to read the package packet The type of , Put this judgment function in demux To realize :
int main(int argc, char *argv[])
{
xdemux demux;
const char* path = "E:\\ffmpeg\\test02.mp4";
cout << "demux.Open = " << demux.Open(path) << endl;
xdecode vdecode;// A class for audio and video unpacking , Decode each with its own
cout << "vdecode.open()" << vdecode.open(demux.CopyVPara()) << endl;
xdecode adecode;
cout << "adecode.open()" << adecode.open(demux.CopyAPara()) << endl;
for (;;)
{
AVPacket* pkt = demux.readfz();
if (demux.isvideo(pkt) == true)
{
vdecode.send(pkt);
AVFrame* frame = vdecode.receive();
}
else
{
adecode.send(pkt);
AVFrame* frame = adecode.receive();
}
if (!pkt)break;
}
QApplication a(argc, argv);
Xplay2 w;
w.show();
return a.exec();
}
AVPacket yes FFmpeg A very important data structure in , It saves knowledge after reuse , Data before decoding ( It's still compressed data ) And some additional information about these data , For example, the time stamp is displayed (pts)、 Decoding timestamp (dts)、 Data duration , The index of the media stream .
For video (Video) Come on ,AVPacket Usually contains a compressed Frame, And audio (Audio) It is possible to include multiple compressed Frame. also , One Packet It could be empty , Does not contain any compressed data , Contains only side data(side data, The container provides information about Packet Some additional information about . for example , Update some stream parameters at the end of coding ).
边栏推荐
- Comparator summary
- Byte order data read / write
- 阿里云开发板vscode开发环境搭建
- Details of bypassing safeseh mechanism by using modules that do not enable safeseh
- M1 pod install pod lint failure solution
- 注重点击,追求更多用户进入网站,可以选择什么出价策略?
- Alibaba cloud development board haas510 connects to the Internet of things platform -- Haas essay solicitation
- PostgreSQL14安装使用教程
- Tool notes - common custom tool classes (regular, random, etc.)
- 2000. reverse word prefix
猜你喜欢

Mémoire de l'examen d'entrée à l'université
![[semidrive source code analysis] [x9 chip startup process] 25 - Introduction to mailbox inter core communication mechanism (code analysis) rpmsg-ipcc RTOS & QNX](/img/90/98faa5856fbc55ff7fda4a3adb3650.png)
[semidrive source code analysis] [x9 chip startup process] 25 - Introduction to mailbox inter core communication mechanism (code analysis) rpmsg-ipcc RTOS & QNX

Pay attention to click and pursue more users to enter the website. What bidding strategy can you choose?

Xcode debugging OpenGLES

Now you must know the pointer

Des File Encryptor based on MFC framework

Paw advanced user guide

对于跨境电商,更侧重收入的出价策略 —Google SEM

Alibaba cloud development board haas510 sends the serial port data to the Internet of things platform

Introduction to database system (Fifth Edition) notes Chapter 1 Introduction
随机推荐
肝了一个月的原创小袁个人博客项目开源啦(博客基本功能都有,还包含后台管理)
动态搜索广告智能查找匹配关键字
Crack WinRAR to ad pop-up window
高考回忆录
Leetcode 2185. Counts the string containing the given prefix
Des File Encryptor based on MFC framework
Axi4 increase burst / wrap burst/ fix burst and narrow transfer
Player screen orientation scheme
Transmission and response of events and use cases
Redis data deletion policy in 2022
[advanced MySQL] query optimization principle and scheme (6)
Comparator summary
PostgreSQL14安装使用教程
Reverse analysis from x86 to x64tips
What is the default gateway
The original Xiaoyuan personal blog project that has been around for a month is open source (the blog has basic functions, including background management)
Brush one question every day /537 Complex multiplication
Factory mode of "object creation" mode
1414. minimum number of Fibonacci numbers with sum K
[video lesson] a full set of tutorials on the design and production of Android studio Internet of things app -- all mastered during the National Day