260 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#ifndef FF_FFPLAY_DEF_H
 | 
						||
#define FF_FFPLAY_DEF_H
 | 
						||
 | 
						||
 | 
						||
#include <inttypes.h>
 | 
						||
#include <math.h>
 | 
						||
#include <limits.h>
 | 
						||
#include <signal.h>
 | 
						||
#include <stdint.h>
 | 
						||
extern "C" {
 | 
						||
#include "libavutil/avstring.h"
 | 
						||
#include "libavutil/eval.h"
 | 
						||
#include "libavutil/mathematics.h"
 | 
						||
#include "libavutil/pixdesc.h"
 | 
						||
#include "libavutil/imgutils.h"
 | 
						||
#include "libavutil/dict.h"
 | 
						||
#include "libavutil/parseutils.h"
 | 
						||
#include "libavutil/samplefmt.h"
 | 
						||
#include "libavutil/avassert.h"
 | 
						||
#include "libavutil/time.h"
 | 
						||
#include "libavformat/avformat.h"
 | 
						||
#include "libavdevice/avdevice.h"
 | 
						||
#include "libswscale/swscale.h"
 | 
						||
#include "libavutil/opt.h"
 | 
						||
#include "libavcodec/avfft.h"
 | 
						||
#include "libswresample/swresample.h"
 | 
						||
}
 | 
						||
#include <SDL.h>
 | 
						||
#include <SDL_thread.h>
 | 
						||
 | 
						||
#include <assert.h>
 | 
						||
 | 
						||
#include "ijksdl_timer.h"
 | 
						||
 | 
						||
#define MAX_QUEUE_SIZE (15 * 1024 * 1024)
 | 
						||
#define MIN_FRAMES 25
 | 
						||
#define EXTERNAL_CLOCK_MIN_FRAMES 2
 | 
						||
#define EXTERNAL_CLOCK_MAX_FRAMES 10
 | 
						||
 | 
						||
/* Step size for volume control in dB */
 | 
						||
#define SDL_VOLUME_STEP (0.75)
 | 
						||
 | 
						||
/* no AV sync correction is done if below the minimum AV sync threshold */
 | 
						||
#define AV_SYNC_THRESHOLD_MIN 0.04
 | 
						||
/* AV sync correction is done if above the maximum AV sync threshold */
 | 
						||
#define AV_SYNC_THRESHOLD_MAX 0.1
 | 
						||
/* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */
 | 
						||
#define AV_SYNC_FRAMEDUP_THRESHOLD 0.1
 | 
						||
/* no AV correction is done if too big error */
 | 
						||
#define AV_NOSYNC_THRESHOLD 10.0
 | 
						||
 | 
						||
 | 
						||
typedef struct FFTrackCacheStatistic
 | 
						||
{
 | 
						||
    int64_t duration;
 | 
						||
    int64_t bytes;
 | 
						||
    int64_t packets;
 | 
						||
} FFTrackCacheStatistic;
 | 
						||
 | 
						||
 | 
						||
typedef struct FFStatistic
 | 
						||
{
 | 
						||
    int64_t vdec_type;
 | 
						||
 | 
						||
    float vfps;
 | 
						||
    float vdps;
 | 
						||
    float avdelay;
 | 
						||
    float avdiff;
 | 
						||
    int64_t bit_rate;
 | 
						||
 | 
						||
    FFTrackCacheStatistic video_cache;
 | 
						||
    FFTrackCacheStatistic audio_cache;
 | 
						||
 | 
						||
    int64_t buf_backwards;
 | 
						||
    int64_t buf_forwards;
 | 
						||
    int64_t buf_capacity;
 | 
						||
    SDL_SpeedSampler2 tcp_read_sampler;
 | 
						||
    int64_t latest_seek_load_duration;
 | 
						||
    int64_t byte_count;
 | 
						||
    int64_t cache_physical_pos;
 | 
						||
    int64_t cache_file_forwards;
 | 
						||
    int64_t cache_file_pos;
 | 
						||
    int64_t cache_count_bytes;
 | 
						||
    int64_t logical_file_size;
 | 
						||
    int drop_frame_count;
 | 
						||
    int decode_frame_count;
 | 
						||
    float drop_frame_rate;
 | 
						||
} FFStatistic;
 | 
						||
 | 
						||
enum RET_CODE
 | 
						||
{
 | 
						||
    RET_ERR_UNKNOWN = -2,                   // 未知错误
 | 
						||
    RET_FAIL = -1,							// 失败
 | 
						||
    RET_OK	= 0,							// 正常
 | 
						||
    RET_ERR_OPEN_FILE,						// 打开文件失败
 | 
						||
    RET_ERR_NOT_SUPPORT,					// 不支持
 | 
						||
    RET_ERR_OUTOFMEMORY,					// 没有内存
 | 
						||
    RET_ERR_STACKOVERFLOW,					// 溢出
 | 
						||
    RET_ERR_NULLREFERENCE,					// 空参考
 | 
						||
    RET_ERR_ARGUMENTOUTOFRANGE,				//
 | 
						||
    RET_ERR_PARAMISMATCH,					//
 | 
						||
    RET_ERR_MISMATCH_CODE,                  // 没有匹配的编解码器
 | 
						||
    RET_ERR_EAGAIN,
 | 
						||
    RET_ERR_EOF
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
typedef struct MyAVPacketList {
 | 
						||
    AVPacket		pkt;    //解封装后的数据
 | 
						||
    struct MyAVPacketList	*next;  //下一个节点
 | 
						||
    int			serial;     //播放序列
 | 
						||
} MyAVPacketList;
 | 
						||
 | 
						||
typedef struct PacketQueue {
 | 
						||
    MyAVPacketList	*first_pkt, *last_pkt;  // 队首,队尾指针
 | 
						||
    int		nb_packets;   // 包数量,也就是队列元素数量
 | 
						||
    int		size;         // 队列所有元素的数据大小总和
 | 
						||
    int64_t		duration; // 队列所有元素的数据播放持续时间
 | 
						||
    int		abort_request; // 用户退出请求标志
 | 
						||
    int		serial;         // 播放序列号,和MyAVPacketList的serial作用相同,但改变的时序稍微有点不同
 | 
						||
    SDL_mutex	*mutex;     // 用于维持PacketQueue的多线程安全(SDL_mutex可以按pthread_mutex_t理解)
 | 
						||
    SDL_cond	*cond;      // 用于读、写线程相互通知(SDL_cond可以按pthread_cond_t理解)
 | 
						||
} PacketQueue;
 | 
						||
 | 
						||
#define VIDEO_PICTURE_QUEUE_SIZE	3       // 图像帧缓存数量
 | 
						||
#define VIDEO_PICTURE_QUEUE_SIZE_MIN        (3)
 | 
						||
#define VIDEO_PICTURE_QUEUE_SIZE_MAX        (16)
 | 
						||
#define VIDEO_PICTURE_QUEUE_SIZE_DEFAULT    (VIDEO_PICTURE_QUEUE_SIZE_MIN)
 | 
						||
#define SUBPICTURE_QUEUE_SIZE		16      // 字幕帧缓存数量
 | 
						||
#define SAMPLE_QUEUE_SIZE           9       // 采样帧缓存数量
 | 
						||
#define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
 | 
						||
 | 
						||
 | 
						||
typedef struct AudioParams {
 | 
						||
    int			freq;                   // 采样率
 | 
						||
    int			channels;               // 通道数
 | 
						||
    int64_t		channel_layout;         // 通道布局,比如2.1声道,5.1声道等
 | 
						||
    enum AVSampleFormat	fmt;            // 音频采样格式,比如AV_SAMPLE_FMT_S16表示为有符号16bit深度,交错排列模式。
 | 
						||
    int			frame_size;             // 一个采样单元占用的字节数(比如2通道时,则左右通道各采样一次合成一个采样单元)
 | 
						||
    int			bytes_per_sec;          // 一秒时间的字节数,比如采样率48Khz,2 channel,16bit,则一秒48000*2*16/8=192000
 | 
						||
} AudioParams;
 | 
						||
 | 
						||
 | 
						||
/* Common struct for handling all types of decoded data and allocated render buffers. */
 | 
						||
// 用于缓存解码后的数据
 | 
						||
typedef struct Frame {
 | 
						||
    AVFrame		*frame;         // 指向数据帧
 | 
						||
    int		serial;             // 帧序列,在seek的操作时serial会变化
 | 
						||
    double		pts;            // 时间戳,单位为秒
 | 
						||
    double		duration;       // 该帧持续时间,单位为秒
 | 
						||
    int64_t pos;
 | 
						||
    int		width;              // 图像宽度
 | 
						||
    int		height;             // 图像高读
 | 
						||
    int		format;             // 对于图像为(enum AVPixelFormat)
 | 
						||
    AVRational sar;
 | 
						||
    int uploaded;
 | 
						||
    int flip_v;
 | 
						||
} Frame;
 | 
						||
 | 
						||
/* 这是一个循环队列,windex是指其中的首元素,rindex是指其中的尾部元素. */
 | 
						||
typedef struct FrameQueue {
 | 
						||
    Frame	queue[FRAME_QUEUE_SIZE];        // FRAME_QUEUE_SIZE  最大size, 数字太大时会占用大量的内存,需要注意该值的设置
 | 
						||
    int		rindex;                         // 读索引。待播放时读取此帧进行播放,播放后此帧成为上一帧
 | 
						||
    int		windex;                         // 写索引
 | 
						||
    int		size;                           // 当前总帧数
 | 
						||
    int		max_size;                       // 可存储最大帧数
 | 
						||
    int keep_last;
 | 
						||
    int rindex_shown;
 | 
						||
    SDL_mutex	*mutex;                     // 互斥量
 | 
						||
    SDL_cond	*cond;                      // 条件变量
 | 
						||
    PacketQueue	*pktq;                      // 数据包缓冲队列
 | 
						||
} FrameQueue;
 | 
						||
 | 
						||
 | 
						||
// 这里讲的系统时钟 是通过av_gettime_relative()获取到的时钟,单位为微妙
 | 
						||
typedef struct Clock {
 | 
						||
    double	pts;            // 时钟基础, 当前帧(待播放)显示时间戳,播放后,当前帧变成上一帧
 | 
						||
    // 当前pts与当前系统时钟的差值, audio、video对于该值是独立的
 | 
						||
    double	pts_drift;      // clock base minus time at which we updated the clock
 | 
						||
    // 当前时钟(如视频时钟)最后一次更新时间,也可称当前时钟时间
 | 
						||
    double	last_updated;   // 最后一次更新的系统时钟
 | 
						||
    double	speed;          // 时钟速度控制,用于控制播放速度
 | 
						||
    // 播放序列,所谓播放序列就是一段连续的播放动作,一个seek操作会启动一段新的播放序列
 | 
						||
    int	serial;             // clock is based on a packet with this serial
 | 
						||
    int	paused;             // = 1 说明是暂停状态
 | 
						||
    // 指向packet_serial
 | 
						||
    int *queue_serial;      /* pointer to the current packet queue serial, used for obsolete clock detection */
 | 
						||
} Clock;
 | 
						||
 | 
						||
/**
 | 
						||
 *音视频同步方式,缺省以音频为基准
 | 
						||
 */
 | 
						||
enum {
 | 
						||
    AV_SYNC_UNKNOW_MASTER = -1,
 | 
						||
    AV_SYNC_AUDIO_MASTER,                   // 以音频为基准
 | 
						||
    AV_SYNC_VIDEO_MASTER,                   // 以视频为基准
 | 
						||
//    AV_SYNC_EXTERNAL_CLOCK,                 // 以外部时钟为基准,synchronize to an external clock */
 | 
						||
};
 | 
						||
 | 
						||
#define fftime_to_milliseconds(ts) (av_rescale(ts, 1000, AV_TIME_BASE))
 | 
						||
#define milliseconds_to_fftime(ms) (av_rescale(ms, AV_TIME_BASE, 1000))
 | 
						||
 | 
						||
extern  AVPacket flush_pkt;
 | 
						||
// 队列相关
 | 
						||
int packet_queue_put(PacketQueue *q, AVPacket *pkt);
 | 
						||
int packet_queue_put_nullpacket(PacketQueue *q, int stream_index);
 | 
						||
int packet_queue_init(PacketQueue *q);
 | 
						||
void packet_queue_flush(PacketQueue *q);
 | 
						||
void packet_queue_destroy(PacketQueue *q);
 | 
						||
void packet_queue_abort(PacketQueue *q);
 | 
						||
void packet_queue_start(PacketQueue *q);
 | 
						||
int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial);
 | 
						||
 | 
						||
/**
 | 
						||
 * @brief 获取帧缓存的数据可以播放的时间长度
 | 
						||
 * @param q 队列本身
 | 
						||
 * @param time_base 用于计算packet的时间戳转换
 | 
						||
 * @param packet_duration 单个包可以播放的时长
 | 
						||
 * @return 返回时长以秒为单位
 | 
						||
 */
 | 
						||
double packet_queue_cache_duration(PacketQueue *q, AVRational time_base, double packet_duration);
 | 
						||
 | 
						||
/* 初始化FrameQueue,视频和音频keep_last设置为1,字幕设置为0 */
 | 
						||
int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last);
 | 
						||
void frame_queue_destory(FrameQueue *f);
 | 
						||
void frame_queue_signal(FrameQueue *f);
 | 
						||
/* 获取队列当前Frame, 在调用该函数前先调用frame_queue_nb_remaining确保有frame可读 */
 | 
						||
Frame *frame_queue_peek(FrameQueue *f);
 | 
						||
 | 
						||
/* 获取当前Frame的下一Frame, 此时要确保queue里面至少有2个Frame */
 | 
						||
// 不管你什么时候调用,返回来肯定不是 NULL
 | 
						||
Frame *frame_queue_peek_next(FrameQueue *f);
 | 
						||
/* 获取last Frame:
 | 
						||
 */
 | 
						||
Frame *frame_queue_peek_last(FrameQueue *f);
 | 
						||
// 获取可写指针
 | 
						||
Frame *frame_queue_peek_writable(FrameQueue *f);
 | 
						||
// 获取可读
 | 
						||
Frame *frame_queue_peek_readable(FrameQueue *f);
 | 
						||
// 更新写指针
 | 
						||
void frame_queue_push(FrameQueue *f);
 | 
						||
/* 释放当前frame,并更新读索引rindex */
 | 
						||
void frame_queue_next(FrameQueue *f);
 | 
						||
int frame_queue_nb_remaining(FrameQueue *f);
 | 
						||
int64_t frame_queue_last_pos(FrameQueue *f);
 | 
						||
 | 
						||
 | 
						||
// 时钟相关
 | 
						||
double get_clock(Clock *c);
 | 
						||
void set_clock_at(Clock *c, double pts, int serial, double time);
 | 
						||
void set_clock(Clock *c, double pts, int serial);
 | 
						||
void init_clock(Clock *c, int *queue_serial);
 | 
						||
 | 
						||
 | 
						||
 void ffp_reset_statistic(FFStatistic *dcc);
 | 
						||
 | 
						||
 | 
						||
 | 
						||
#endif // FF_FFPLAY_DEF_H
 |