Files
gdmp/ff_ffplay.h
2025-09-25 16:56:53 +08:00

235 lines
8.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef FF_FFPLAY_H
#define FF_FFPLAY_H
#include <thread>
#include <functional>
#include "ffmsg_queue.h"
#include "ff_ffplay_def.h"
#include "sonic.h"
extern "C" {
#include "libavcodec/avcodec.h"
}
class Decoder
{
public:
int packet_pending_ = 0;
AVPacket pkt_;
PacketQueue *queue_; // 数据包队列
AVCodecContext *avctx_; // 解码器上下文
int pkt_serial_; // 包序列
int finished_; // =0解码器处于工作状态=非0解码器处于空闲状态
std::thread *decoder_thread_ = NULL;
int64_t start_pts;
AVRational start_pts_tb;
int64_t next_pts;
AVRational next_pts_tb;
Decoder();
~Decoder();
void decoder_init(AVCodecContext *avctx, PacketQueue *queue);
// 创建和启动线程
int decoder_start(enum AVMediaType codec_type, const char *thread_name, void* arg);
// 停止线程
void decoder_abort(FrameQueue *fq);
void decoder_destroy();
int decoder_decode_frame(AVFrame *frame);
int get_video_frame(AVFrame *frame);
int queue_picture(FrameQueue *fq, AVFrame *src_frame, double pts,
double duration, int64_t pos, int serial);
int audio_thread(void* arg);
int video_thread(void* arg);
};
class FFPlayer
{
public:
FFPlayer();
int ffp_create();
void ffp_destroy();
int ffp_prepare_async_l(char *file_name);
// 播放控制
int ffp_start_l();
int ffp_stop_l();
int stream_open( const char *file_name);
void stream_close();
// 打开指定stream对应解码器、创建解码线程、以及初始化对应的输出
int stream_component_open(int stream_index);
// 关闭指定stream的解码线程释放解码器资源
void stream_component_close(int stream_index);
int audio_open(int64_t wanted_channel_layout,
int wanted_nb_channels, int wanted_sample_rate,
struct AudioParams *audio_hw_params);
void audio_close();
//获取播放时长
long ffp_get_duration_l();
long ffp_get_current_position_l();
// 暂停恢复
int ffp_pause_l();
void toggle_pause(int pause_on);
void toggle_pause_l(int pause_on);
void stream_update_pause_l();
void stream_toggle_pause_l(int pause_on);
// seek相关
int ffp_seek_to_l(long msec);
// 单位是秒 整数
int ffp_forward_to_l(long incr);
// 单位是秒 负数
int ffp_back_to_l(long incr);
int ffp_forward_or_back_to_l(long incr);
void stream_seek(int64_t pos, int64_t rel, int seek_by_bytes);
// 截屏相关
int ffp_screenshot_l(char *screen_path);
void screenshot(AVFrame *frame);
// 变速相关
int get_target_frequency();
int get_target_channels();
void ffp_set_playback_rate(float rate);
float ffp_get_playback_rate();
bool is_normal_playback_rate();
int ffp_get_playback_rate_change();
void ffp_set_playback_rate_change(int change);
//音量相关
void ffp_set_playback_volume(int value);
//播放完毕相关判断 1. av_read_frame返回eof; 2. audio没有数据可以输出; 3.video没有数据可以输出
void check_play_finish(); //如果已经结束则通知ui调用停止函数
// 供外包获取信息
int64_t ffp_get_property_int64(int id, int64_t default_value);
void ffp_track_statistic_l(AVStream *st, PacketQueue *q, FFTrackCacheStatistic *cache);
void ffp_audio_statistic_l();
void ffp_video_statistic_l();
MessageQueue msg_queue_;
char *input_filename_;
int realtime = 0;
int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue);
int read_thread();
std::thread *read_thread_;
int video_refresh_thread();
void video_refresh(double *remaining_time);
double vp_duration( Frame *vp, Frame *nextvp);
double compute_target_delay(double delay);
void update_video_pts(double pts, int64_t pos, int serial);
// 视频画面输出相关
std::thread *video_refresh_thread_ = NULL;
std::function<int(const Frame *)> video_refresh_callback_ = NULL;
void AddVideoRefreshCallback(std::function<int(const Frame *)> callback);
int get_master_sync_type();
double get_master_clock();
int av_sync_type = AV_SYNC_AUDIO_MASTER; // 音视频同步类型, 默认audio master
Clock audclk; // 音频时钟
Clock vidclk; // 视频时钟
// Clock extclk;
double audio_clock = 0; // 当前音频帧的PTS+当前帧Duration
int audio_clock_serial; // 播放序列seek可改变此值, 解码后保存
int64_t audio_callback_time = 0;
// 帧队列
FrameQueue pictq; // 视频Frame队列
FrameQueue sampq; // 采样Frame队列
// 包队列
PacketQueue audioq; // 音频packet队列
PacketQueue videoq; // 视频队列
int abort_request = 0;
AVStream *audio_st = NULL; // 音频流
AVStream *video_st = NULL; // 音频流
int force_refresh = 0;
double frame_timer = 0;
int audio_stream = -1;
int video_stream = -1;
Decoder auddec; // 音频解码器
Decoder viddec; // 视频解码器
int eof = 0;
int audio_no_data = 0;
int video_no_data = 0;
AVFormatContext *ic = NULL;
int paused = 0;
// 音频输出相关
struct AudioParams audio_src; // 保存最新解码的音频参数
struct AudioParams audio_tgt; // 保存SDL音频输出需要的参数
struct SwrContext *swr_ctx = NULL; // 音频重采样context
int audio_hw_buf_size = 0; // SDL音频缓冲区的大小(字节为单位)
// 指向待播放的一帧音频数据指向的数据区将被拷入SDL音频缓冲区。若经过重采样则指向audio_buf1
// 否则指向frame中的音频
uint8_t *audio_buf = NULL; // 指向需要重采样的数据
uint8_t *audio_buf1 = NULL; // 指向重采样后的数据
unsigned int audio_buf_size = 0; // 待播放的一帧音频数据(audio_buf指向)的大小
unsigned int audio_buf1_size = 0; // 申请到的音频缓冲区audio_buf1的实际尺寸
int audio_buf_index = 0; // 更新拷贝位置 当前音频帧中已拷入SDL音频缓冲区
int audio_write_buf_size;
int audio_volume = 50; // 音量相关
int startup_volume = 50; // 起始音量
// seek相关
int64_t seek_req = 0;
int64_t seek_rel = 0;
int64_t seek_flags = 0;
int64_t seek_pos = 0; // seek的位置
// 截屏相关
bool req_screenshot_ = false;
char *screen_path_ = NULL;
//单步运行
int step = 0;
int framedrop = 1;
int frame_drops_late = 0;
int pause_req = 0;
int auto_resume = 0;
int buffering_on = 0;
// 变速相关
float pf_playback_rate = 1.0; // 播放速率
int pf_playback_rate_changed = 0; // 播放速率改变
// 变速相关
sonicStreamStruct *audio_speed_convert = nullptr;
int max_frame_duration = 3600;
// 统计相关的操作
FFStatistic stat;
};
inline static void ffp_notify_msg1(FFPlayer *ffp, int what)
{
msg_queue_put_simple3(&ffp->msg_queue_, what, 0, 0);
}
inline static void ffp_notify_msg2(FFPlayer *ffp, int what, int arg1)
{
msg_queue_put_simple3(&ffp->msg_queue_, what, arg1, 0);
}
inline static void ffp_notify_msg3(FFPlayer *ffp, int what, int arg1, int arg2)
{
msg_queue_put_simple3(&ffp->msg_queue_, what, arg1, arg2);
}
inline static void ffp_notify_msg4(FFPlayer *ffp, int what, int arg1, int arg2, void *obj, int obj_len)
{
msg_queue_put_simple4(&ffp->msg_queue_, what, arg1, arg2, obj, obj_len);
}
inline static void ffp_remove_msg(FFPlayer *ffp, int what)
{
msg_queue_remove(&ffp->msg_queue_, what);
}
#endif // FF_FFPLAY_H