|
|
|
@ -1,16 +1,23 @@
|
|
|
|
|
#include "MediaPlayer.h" |
|
|
|
|
|
|
|
|
|
MediaPlayer::MediaPlayer() : m_avformat_ctx(nullptr), |
|
|
|
|
m_video_avdecoder(new MediaAVDecoder), |
|
|
|
|
m_audio_avdecoder(new MediaAVDecoder), |
|
|
|
|
m_video_avdecoder(nullptr), |
|
|
|
|
m_audio_avdecoder(nullptr), |
|
|
|
|
m_render_receive_obj(nullptr), |
|
|
|
|
m_sws_spec(new v_sws_spec) |
|
|
|
|
m_sws_spec(nullptr), |
|
|
|
|
m_sws_ctx(nullptr), |
|
|
|
|
m_use_opt(nullptr), |
|
|
|
|
m_video_af_frame(nullptr), |
|
|
|
|
m_video_ot_frame(nullptr), |
|
|
|
|
m_audio_af_frame(nullptr), |
|
|
|
|
m_audio_ot_frame(nullptr) |
|
|
|
|
{ |
|
|
|
|
m_sws_spec = new v_sws_spec; |
|
|
|
|
m_use_opt = new use_opt; |
|
|
|
|
m_sws_spec->info_state = true; |
|
|
|
|
} |
|
|
|
|
MediaPlayer::~MediaPlayer() |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
char *CharAVPixelFormat[]{ |
|
|
|
|
"AV_PIX_FMT_NONE", |
|
|
|
@ -412,6 +419,7 @@ bool MediaPlayer::open_file(const char *filename)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
// 查找视频解码器并打开解码器
|
|
|
|
|
m_video_avdecoder = new MediaAVDecoder; |
|
|
|
|
if (!m_video_avdecoder->init(m_avformat_ctx, AVMEDIA_TYPE_VIDEO)) |
|
|
|
|
{ |
|
|
|
|
free_avformat_ctx(); |
|
|
|
@ -420,6 +428,8 @@ bool MediaPlayer::open_file(const char *filename)
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
m_use_opt->pix_fmt = AV_PIX_FMT_YUV420P; |
|
|
|
|
m_use_opt->aspect_type = keep_aspect_ratio; |
|
|
|
|
m_sws_ctx = sws_getContext( |
|
|
|
|
m_video_avdecoder->m_avcodec_context->width, |
|
|
|
|
m_video_avdecoder->m_avcodec_context->height, |
|
|
|
@ -433,7 +443,9 @@ bool MediaPlayer::open_file(const char *filename)
|
|
|
|
|
NULL // param
|
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 查找音频解码器并打开解码器
|
|
|
|
|
m_audio_avdecoder = new MediaAVDecoder; |
|
|
|
|
if (!m_audio_avdecoder->init(m_avformat_ctx, AVMEDIA_TYPE_AUDIO)) |
|
|
|
|
{ |
|
|
|
|
free_avformat_ctx(); |
|
|
|
@ -583,20 +595,20 @@ void MediaPlayer::demux_thread()
|
|
|
|
|
// printf("video packet queue size: %d, video frame queue size:%d, audio packet queue size:%d,audio frame queue size :%d\n",
|
|
|
|
|
// m_video_packet_queue.size(), m_video_frame_queue.size(), m_audio_packet_queue.size(), m_audio_frame_queue.size());
|
|
|
|
|
{ |
|
|
|
|
std::lock_guard <std::mutex>locker(m_pkt_video_queue_mutex); |
|
|
|
|
if (m_video_frame_queue.size() > PACKETSIZE) |
|
|
|
|
{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
std::lock_guard<std::mutex> locker(m_pkt_video_queue_mutex); |
|
|
|
|
if (m_video_frame_queue.size() > PACKETSIZE) |
|
|
|
|
{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
std::lock_guard <std::mutex>locker(m_pkt_audio_queue_mutex); |
|
|
|
|
if (m_audio_frame_queue.size() > PACKETSIZE) |
|
|
|
|
{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
{ |
|
|
|
|
std::lock_guard<std::mutex> locker(m_pkt_audio_queue_mutex); |
|
|
|
|
if (m_audio_frame_queue.size() > PACKETSIZE) |
|
|
|
|
{ |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
MediaAVPacket *packet = new MediaAVPacket; |
|
|
|
|
int result = av_read_frame(m_avformat_ctx, packet->m_pakcet); |
|
|
|
|
if (result < 0) |
|
|
|
@ -652,7 +664,7 @@ void MediaPlayer::video_decode_thread()
|
|
|
|
|
m_video_packet_queue.pop_front(); |
|
|
|
|
video_decode(video_pkt); |
|
|
|
|
delete video_pkt; |
|
|
|
|
video_pkt=nullptr; |
|
|
|
|
video_pkt = nullptr; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
@ -670,7 +682,7 @@ void MediaPlayer::video_decode_thread()
|
|
|
|
|
video_pkt->m_pakcet->size = 0; |
|
|
|
|
video_decode(video_pkt); |
|
|
|
|
delete video_pkt; |
|
|
|
|
video_pkt=nullptr; |
|
|
|
|
video_pkt = nullptr; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -713,7 +725,7 @@ void MediaPlayer::audio_decode_thread()
|
|
|
|
|
m_audio_packet_queue.pop_front(); |
|
|
|
|
audio_decode(audio_pkt); |
|
|
|
|
delete audio_pkt; |
|
|
|
|
audio_pkt=nullptr; |
|
|
|
|
audio_pkt = nullptr; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
@ -730,7 +742,7 @@ void MediaPlayer::audio_decode_thread()
|
|
|
|
|
audio_pkt->m_pakcet->size = 0; |
|
|
|
|
audio_decode(audio_pkt); |
|
|
|
|
delete audio_pkt; |
|
|
|
|
audio_pkt=nullptr; |
|
|
|
|
audio_pkt = nullptr; |
|
|
|
|
printf("audio_decodec thread finished..................\n"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -739,9 +751,8 @@ void MediaPlayer::audio_decode_thread()
|
|
|
|
|
} |
|
|
|
|
void MediaPlayer::render_video_thread() |
|
|
|
|
{ |
|
|
|
|
int frameSize = av_image_get_buffer_size(m_video_avdecoder->m_avcodec_context->pix_fmt, m_video_avdecoder->m_avcodec_context->width, m_video_avdecoder->m_avcodec_context->height, 1); |
|
|
|
|
uint8_t *buffer = (uint8_t *)av_malloc(frameSize); // 指向YUV420的数据部分
|
|
|
|
|
|
|
|
|
|
m_frameSize = av_image_get_buffer_size(m_video_avdecoder->m_avcodec_context->pix_fmt, m_video_avdecoder->m_avcodec_context->width, m_video_avdecoder->m_avcodec_context->height, 1); |
|
|
|
|
buffer = (uint8_t *)av_malloc(m_frameSize); // 指向YUV420的数据部分
|
|
|
|
|
static double m_previous_pts_diff = 40e-3; |
|
|
|
|
static double m_previous_pts = 0; |
|
|
|
|
static bool m_first_frame = true; |
|
|
|
@ -855,7 +866,7 @@ void MediaPlayer::render_video_thread()
|
|
|
|
|
|
|
|
|
|
QMetaObject::invokeMethod( |
|
|
|
|
QApplication::instance(), [=]() |
|
|
|
|
{ m_render_receive_obj->update_image(m_video_ot_frame, m_sws_spec); }, |
|
|
|
|
{ m_render_receive_obj->update_image(m_video_ot_frame, m_sws_spec, m_use_opt); }, |
|
|
|
|
Qt::QueuedConnection); |
|
|
|
|
} |
|
|
|
|
av_free(buffer); |
|
|
|
@ -883,6 +894,7 @@ void MediaPlayer::render_audio_thread()
|
|
|
|
|
locker.unlock(); |
|
|
|
|
|
|
|
|
|
m_audio_current_pts = m_audio_af_frame->m_frame->best_effort_timestamp * av_q2d(m_audio_avdecoder->m_avstream->time_base); |
|
|
|
|
|
|
|
|
|
// the amount of time until we need to display this frame
|
|
|
|
|
double diff = m_audio_current_pts - m_previous_audio_pts; |
|
|
|
|
if (m_first_frame) |
|
|
|
@ -922,6 +934,11 @@ void MediaPlayer::render_audio_thread()
|
|
|
|
|
int32_t size = m_audio_af_frame->m_frame->nb_samples * bytes_per_sample * m_audio_af_frame->m_frame->channels; |
|
|
|
|
char *data = av_pcm_clone(m_audio_af_frame->m_frame); |
|
|
|
|
m_current_aduio_render_time = av_gettime(); |
|
|
|
|
// 音频时钟无效判断
|
|
|
|
|
if (m_current_aduio_render_time != AV_NOPTS_VALUE) |
|
|
|
|
{
|
|
|
|
|
emit signals_play_time_changed(this); |
|
|
|
|
} |
|
|
|
|
SDL_QueueAudio(m_current_audio_deviceId, data, size); |
|
|
|
|
free((void *)data); |
|
|
|
|
} |
|
|
|
@ -975,10 +992,11 @@ void MediaPlayer::get_video_size(int &width, int &height)
|
|
|
|
|
} |
|
|
|
|
void MediaPlayer::set_video_size(int _width, int _height) |
|
|
|
|
{ |
|
|
|
|
if (m_sws_spec && m_video_avdecoder) |
|
|
|
|
if (m_use_opt) |
|
|
|
|
{ |
|
|
|
|
m_sws_spec->width = _width; |
|
|
|
|
m_sws_spec->height = _height; |
|
|
|
|
pause_or_resume(); |
|
|
|
|
m_use_opt->width = _width; |
|
|
|
|
m_use_opt->height = _height; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
v_sws_spec *MediaPlayer::get_sws_specs() |
|
|
|
@ -1005,3 +1023,11 @@ void MediaPlayer::register_render_windows_callback(SDL2RenderWidget *receiver)
|
|
|
|
|
{ |
|
|
|
|
m_render_receive_obj = receiver; |
|
|
|
|
} |
|
|
|
|
int MediaPlayer::get_duration() |
|
|
|
|
{ |
|
|
|
|
return m_avformat_ctx ? round(m_avformat_ctx->duration * av_q2d(AV_TIME_BASE_Q)) : 0; // 时间转化为秒
|
|
|
|
|
} |
|
|
|
|
int MediaPlayer::get_time() |
|
|
|
|
{ |
|
|
|
|
return round(m_current_aduio_render_time); |
|
|
|
|
} |