音视频项目—基于FFmpeg和SDL的音视频播放器解析(三)

介绍

在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器

如果您不理解本文,可参考我的前一篇文章音视频项目—基于FFmpeg和SDL的音视频播放器解析(二)

解析

在本文中,我们将解析用来解封装的线程的线程类 demuxthread,我们先看看总体的 .h 代码

#pragma once
#ifndef DEMUXTHREAD_H_
#define DEMUXTHREAD_H_
#include"thread.h"
#include"avpacketqueue.h"

#ifdef __cplusplus

extern "C" {
#include"libavutil/avutil.h"
#include"libavformat/avformat.h"
}

#endif // __cplusplus


class DemuxThread : public Thread
{
public:
	DemuxThread(AVPacketQueue* audio_packet_q, AVPacketQueue* video_packet_q);
	~DemuxThread();
	int Init(const string& url);
	int Start();
	int Stop();
	void Run();
	AVCodecParameters* AudioCodecParameters();
	AVCodecParameters* VideoCodecParameters();
	AVRational AudioStreamTimebase();
	AVRational VideoStreamTimebase();
private:
	string url;
	AVFormatContext* ifmt_ctx = nullptr;
	AVPacketQueue* audio_packet_q = nullptr;
	AVPacketQueue* video_packet_q = nullptr;
	int audio_index = -1;
	int video_index = -1;
};

#endif

OK,有了总体的认识,我们先从私有成员讲起,然后再讲公有成员。

私有成员

首先有一个字符串的 url,可以用在未来的输入地址上。然后有 AVFormatContext,这是 ffmpeg 中自带的结构体,是格式上下文,这里不深究,有兴趣的可以看看雷霄骅的博客,在他的博客中有比较深入的探讨。

然后有两个 AVPacketQueue 的成员变量,这个结构体是我们自定义的,未来会讲到。这两个分别存储音频(audio)的数据包(Packet)和视频(video)的数据包。接着有两个 int 变量,表示相关的包在流中的位置,audio_index 就是流中音频包的位置,video_index 就是流中视频包的位置。

公有成员

我们看到公有变量全都是函数,有构造函数,析构函数,其他函数。

我们首先讲构造函数,这比较好理解,就是两个 AVPacketQueue 的初始化。

DemuxThread::DemuxThread(AVPacketQueue* audio_packet_q, AVPacketQueue* video_packet_q) {
	this->audio_packet_q = audio_packet_q;
	this->video_packet_q = video_packet_q;
}

然后我们看看 Start 和 Stop 函数,分别是开始与结束的函数。

int DemuxThread::Start() {
	mythread = new thread(&Run, this);
	if (!mythread) {
		perror("demuxthread: new a thread failed");
		return -1;
	}
	return 0;
}
int DemuxThread::Stop() {
	Thread::Stop();
	avformat_close_input(&ifmt_ctx);
	return 0;
}

在 Start 函数中,我们 new 了一个 thread 线程,如果创建变量失败,则打印错误信息,这里也比较好理解。

在Stop 函数中,我们就用了继承自 Thread 父类的 Stop 方法,功能是销毁线程变量,感兴趣的可以看一下上文基于FFmpeg和SDL的音视频播放器解析(二)。接着我们使用了 avformat_close_input 这个 ffmpeg 自带的函数,显然这是用来关闭输入文件的函数,输入的参数就是 AVFormatContext。

好了,剩下没解析的六个函数 Init,Run,AudioCodecParameters,VideoCodecParameters,AudioStreamTimebase,VideoStreamTimebase,我们将会在下一篇文章中解析,会相对复杂一点,不过有了今天这篇文章的基础,相信大家也会更加容易理解。

欲知后事如何,请听下回分解。

你可能感兴趣的:(音视频,ffmpeg)