ijkplayer源码---FFPlayer结构体1_qq_15255121的专栏-CSDN博客
int seek_by_bytes;
if (ffp->seek_by_bytes < 0)
ffp->seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT) && strcmp("ogg", ic->iformat->name);
#define AVSEEK_FLAG_BYTE 2 ///< seeking based on position in bytes
AVInputFormat
/**
* Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
* AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
* AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
*/
int flags;
typedef struct VideoState
int seek_flags;
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
{
if (!is->seek_req) {
is->seek_pos = pos;
is->seek_rel = rel;
is->seek_flags &= ~AVSEEK_FLAG_BYTE;
if (seek_by_bytes)
is->seek_flags |= AVSEEK_FLAG_BYTE;
is->seek_req = 1;
SDL_CondSignal(is->continue_read_thread);
}
}
static int is_realtime(AVFormatContext *s){
ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
}
seek_by_bytes 没有使用只做了标识,通过上面可以知道AVFormat支持不连续时间戳并且格式是ogg,支持按字节seek
在VideoState中发现了一个seek_flags,发现有对它赋值为AVSEEK_FLAG_BYTE,但是调用的地方都不设置。以至于到最后调用avformat_seek_file的时候,也不能使用。
通过上面ijk的代码应该是屏蔽掉了按字节寻址。不过后续我们做二次开发应该能打开。
int display_disable;
static void video_refresh(FFPlayer *opaque, double *remaining_time)
{
if (!ffp->display_disable && is->show_mode != SHOW_MODE_VIDEO && is->audio_st) {
time = av_gettime_relative() / 1000000.0;
if (is->force_refresh || is->last_vis_time + ffp->rdftspeed < time) {
video_display2(ffp);
is->last_vis_time = time;
}
*remaining_time = FFMIN(*remaining_time, is->last_vis_time + ffp->rdftspeed - time);
}
。。。。。
if (!ffp->display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
video_display2(ffp);
。。。。。。。
}
上面都调用了video_display2大致可以猜出用来显示图像的,那么这个字段的意思也就是是否不允许显示
int show_status;
if (ffp->show_status) {
static int64_t last_time;
int64_t cur_time;
int aqsize, vqsize, sqsize __unused;
double av_diff;
cur_time = av_gettime_relative();
if (!last_time || (cur_time - last_time) >= 30000) {
aqsize = 0;
vqsize = 0;
sqsize = 0;
if (is->audio_st)
aqsize = is->audioq.size;
if (is->video_st)
vqsize = is->videoq.size;
#ifdef FFP_MERGE
if (is->subtitle_st)
sqsize = is->subtitleq.size;
#else
sqsize = 0;
#endif
av_diff = 0;
if (is->audio_st && is->video_st)
av_diff = get_clock(&is->audclk) - get_clock(&is->vidclk);
else if (is->video_st)
av_diff = get_master_clock(is) - get_clock(&is->vidclk);
else if (is->audio_st)
av_diff = get_master_clock(is) - get_clock(&is->audclk);
av_log(NULL, AV_LOG_INFO,
"%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
get_master_clock(is),
(is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
av_diff,
is->frame_drops_early + is->frame_drops_late,
aqsize / 1024,
vqsize / 1024,
sqsize,
is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0,
is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0);
fflush(stdout);
last_time = cur_time;
}
}
这一段没有理解什么意思,通过 fflush(stdout);大概猜测是控制台输出一些东西。
通过别人的解析也能大概猜测到
命令行窗口是否显示相关文件信息
int av_sync_type;
enum {
AV_SYNC_AUDIO_MASTER, /* default choice */
AV_SYNC_VIDEO_MASTER,
AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
};
音视频同步的三种方案
以音频为准
以视频为准
以时钟为准
int64_t start_time;
ffp->start_time = AV_NOPTS_VALUE;
static int read_thread(void *arg){
if (ffp->start_time != AV_NOPTS_VALUE) {
int64_t timestamp;
timestamp = ffp->start_time;
/* add the stream start time */
if (ic->start_time != AV_NOPTS_VALUE)
timestamp += ic->start_time;
ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
is->filename, (double)timestamp / AV_TIME_BASE);
}
}
}
开始播放的时间
int fast;
AV_CODEC_FLAG2_FAST
是否允许不符合规范的加速技巧
int genpts;
#define AVFMT_FLAG_GENPTS 0x0001 ///< Generate missing pts even if it requires parsing future frames.
int lowres;
#if FF_API_LOWRES
attribute_deprecated
int av_codec_get_lowres(const AVCodecContext *avctx);
attribute_deprecated
void av_codec_set_lowres(AVCodecContext *avctx, int val);
#endif
支持的最小分辨率,已经不推荐使用
int decoder_reorder_pts;
static int decoder_decode_frame(FFPlayer *ffp, Decoder *d, AVFrame *frame, AVSubtitle *sub) {
{
switch (d->avctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
ret = avcodec_receive_frame(d->avctx, frame);
if (ret >= 0) {
ffp->stat.vdps = SDL_SpeedSamplerAdd(&ffp->vdps_sampler, FFP_SHOW_VDPS_AVCODEC, "vdps[avcodec]");
if (ffp->decoder_reorder_pts == -1) {
frame->pts = frame->best_effort_timestamp;
} else if (!ffp->decoder_reorder_pts) {
frame->pts = frame->pkt_dts;
}
}
break;
}
如果不设置,使用帧的最佳预测值,如果decoder_reorder_pts为0那就使用AVpacket的解码时间
int autoexit;
播放成功是否自动退出播放器
int loop;
循坏播放几遍
int framedrop;
视频可以丢的帧
int64_t seek_at_start;
开始播放时seek到的位置
int subtitle;
是否支持字幕
int infinite_buffer;
缓冲区是否是无限的
enum ShowMode show_mode;
enum ShowMode {undefined
SHOW_MODE_NONE = -1,//显示窗口自适应
SHOW_MODE_VIDEO = 0,//显示视频
SHOW_MODE_WAVES,//显示音频图形
SHOW_MODE_RDFT, //自适应滤波器
SHOW_MODE_NB
};
char *audio_codec_name;
char *subtitle_codec_name;
char *video_codec_name;
通过名字指定解码器
static int stream_component_open(FFPlayer *ffp, int stream_index)
{
switch (avctx->codec_type) {
case AVMEDIA_TYPE_AUDIO : is->last_audio_stream = stream_index; forced_codec_name = ffp->audio_codec_name; break;
case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; forced_codec_name = ffp->subtitle_codec_name; break;
case AVMEDIA_TYPE_VIDEO : is->last_video_stream = stream_index; forced_codec_name = ffp->video_codec_name; break;
default: break;
}
if (forced_codec_name)
codec = avcodec_find_decoder_by_name(forced_codec_name);
if (!codec) {
if (forced_codec_name) av_log(NULL, AV_LOG_WARNING,
"No codec could be found with name '%s'\n", forced_codec_name);
else av_log(NULL, AV_LOG_WARNING,
"No codec could be found with id %d\n", avctx->codec_id);
ret = AVERROR(EINVAL);
goto fail;
}
}
double rdftspeed;
滤波器速度
int find_stream_info;
是否查找流信息
int64_t audio_callback_time;
音频clock回调的时间
SDL_Aout *aout;
SDL_Vout *vout;
音频和视频的输出