|
@@ -6,7 +6,7 @@
|
|
|
|
|
|
#include "VideoPlayer.h"
|
|
|
|
|
|
-#include "Audio/PcmVolumeControl.h"
|
|
|
+#include "PcmPlayer/PcmPlayer_SDL.h"
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
@@ -19,12 +19,16 @@ VideoPlayer::VideoPlayer()
|
|
|
|
|
|
mVideoPlayerCallBack = nullptr;
|
|
|
|
|
|
- mAudioID = 0;
|
|
|
+// mAudioID = 0;
|
|
|
mIsMute = false;
|
|
|
|
|
|
mIsNeedPause = false;
|
|
|
|
|
|
mVolume = 1;
|
|
|
+
|
|
|
+ mPcmPlayer = new PcmPlayer_SDL();
|
|
|
+
|
|
|
+ this->setSingleMode(true);
|
|
|
}
|
|
|
|
|
|
VideoPlayer::~VideoPlayer()
|
|
@@ -38,7 +42,7 @@ bool VideoPlayer::initPlayer()
|
|
|
|
|
|
if (!isInited)
|
|
|
{
|
|
|
- av_register_all(); //初始化FFMPEG 调用了这个才能正常使用编码器和解码器
|
|
|
+// av_register_all(); //初始化FFMPEG 调用了这个才能正常使用编码器和解码器
|
|
|
avformat_network_init(); //支持打开网络文件
|
|
|
|
|
|
isInited = true;
|
|
@@ -68,19 +72,20 @@ bool VideoPlayer::startPlay(const std::string &filePath)
|
|
|
mFilePath = filePath;
|
|
|
|
|
|
//启动新的线程实现读取视频文件
|
|
|
- std::thread([&](VideoPlayer *pointer)
|
|
|
- {
|
|
|
- pointer->readVideoFile();
|
|
|
+// std::thread([&](VideoPlayer *pointer)
|
|
|
+// {
|
|
|
+// pointer->readVideoFile();
|
|
|
|
|
|
- }, this).detach();
|
|
|
+// }, this).detach();
|
|
|
+ this->start();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
-bool VideoPlayer::replay()
|
|
|
+bool VideoPlayer::replay(bool isWait)
|
|
|
{
|
|
|
- stop();
|
|
|
+ stop(isWait);
|
|
|
|
|
|
startPlay(mFilePath);
|
|
|
|
|
@@ -140,7 +145,8 @@ bool VideoPlayer::stop(bool isWait)
|
|
|
{
|
|
|
while(!mIsReadThreadFinished)
|
|
|
{
|
|
|
- mSleep(3);
|
|
|
+ fprintf(stderr, "mIsReadThreadFinished=%d \n", mIsReadThreadFinished);
|
|
|
+ mSleep(100);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -156,9 +162,16 @@ void VideoPlayer::seek(int64_t pos)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void VideoPlayer::setMute(bool isMute)
|
|
|
+{
|
|
|
+ mIsMute = isMute;
|
|
|
+ mPcmPlayer->setMute(isMute);
|
|
|
+}
|
|
|
+
|
|
|
void VideoPlayer::setVolume(float value)
|
|
|
{
|
|
|
mVolume = value;
|
|
|
+ mPcmPlayer->setVolume(value);
|
|
|
}
|
|
|
|
|
|
double VideoPlayer::getCurrentTime()
|
|
@@ -171,71 +184,100 @@ int64_t VideoPlayer::getTotalTime()
|
|
|
return pFormatCtx->duration;
|
|
|
}
|
|
|
|
|
|
-int VideoPlayer::openSDL()
|
|
|
+//int VideoPlayer::openSDL()
|
|
|
+//{
|
|
|
+// ///打开SDL,并设置播放的格式为:AUDIO_S16LSB 双声道,44100hz
|
|
|
+// ///后期使用ffmpeg解码完音频后,需要重采样成和这个一样的格式,否则播放会有杂音
|
|
|
+// SDL_AudioSpec wanted_spec, spec;
|
|
|
+// int wanted_nb_channels = 2;
|
|
|
+//// int samplerate = 44100;
|
|
|
+// int samplerate = m_out_sample_rate;
|
|
|
+
|
|
|
+// wanted_spec.channels = wanted_nb_channels;
|
|
|
+// wanted_spec.freq = samplerate;
|
|
|
+// wanted_spec.samples = FFMAX(512, 2 << av_log2(wanted_spec.freq / 30));
|
|
|
+// wanted_spec.format = AUDIO_S16SYS; // 具体含义请查看“SDL宏定义”部分
|
|
|
+// wanted_spec.silence = 0; // 0指示静音
|
|
|
+//// wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; // 自定义SDL缓冲区大小
|
|
|
+// wanted_spec.callback = sdlAudioCallBackFunc; // 回调函数
|
|
|
+// wanted_spec.userdata = this; // 传给上面回调函数的外带数据
|
|
|
+
|
|
|
+// int num = SDL_GetNumAudioDevices(0);
|
|
|
+// for (int i=0;i<num;i++)
|
|
|
+// {
|
|
|
+// mAudioID = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(i,0), false, &wanted_spec, &spec,0);
|
|
|
+// if (mAudioID > 0)
|
|
|
+// {
|
|
|
+// break;
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+// /* 检查实际使用的配置(保存在spec,由SDL_OpenAudio()填充) */
|
|
|
+//// if (spec.format != AUDIO_S16SYS)
|
|
|
+// if (mAudioID <= 0)
|
|
|
+// {
|
|
|
+// mIsAudioThreadFinished = true;
|
|
|
+// return -1;
|
|
|
+// }
|
|
|
+//fprintf(stderr, "mAudioID=%d\n\n\n\n\n\n", mAudioID);
|
|
|
+// return 0;
|
|
|
+//}
|
|
|
+
|
|
|
+//void VideoPlayer::closeSDL()
|
|
|
+//{
|
|
|
+// if (mAudioID > 0)
|
|
|
+// {
|
|
|
+// SDL_LockAudioDevice(mAudioID);
|
|
|
+// SDL_PauseAudioDevice(mAudioID, 1);
|
|
|
+// SDL_UnlockAudioDevice(mAudioID);
|
|
|
+
|
|
|
+// SDL_CloseAudioDevice(mAudioID);
|
|
|
+// }
|
|
|
+
|
|
|
+// mAudioID = 0;
|
|
|
+//}
|
|
|
+
|
|
|
+
|
|
|
+static int CheckInterrupt(void* ctx)
|
|
|
{
|
|
|
- ///打开SDL,并设置播放的格式为:AUDIO_S16LSB 双声道,44100hz
|
|
|
- ///后期使用ffmpeg解码完音频后,需要重采样成和这个一样的格式,否则播放会有杂音
|
|
|
- SDL_AudioSpec wanted_spec, spec;
|
|
|
- int wanted_nb_channels = 2;
|
|
|
-// int samplerate = 44100;
|
|
|
- int samplerate = out_sample_rate;
|
|
|
-
|
|
|
- wanted_spec.channels = wanted_nb_channels;
|
|
|
- wanted_spec.samples = FFMAX(512, 2 << av_log2(wanted_spec.freq / 30));
|
|
|
- wanted_spec.freq = samplerate;
|
|
|
- wanted_spec.format = AUDIO_S16SYS; // 具体含义请查看“SDL宏定义”部分
|
|
|
- wanted_spec.silence = 0; // 0指示静音
|
|
|
-// wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; // 自定义SDL缓冲区大小
|
|
|
- wanted_spec.callback = sdlAudioCallBackFunc; // 回调函数
|
|
|
- wanted_spec.userdata = this; // 传给上面回调函数的外带数据
|
|
|
-
|
|
|
- int num = SDL_GetNumAudioDevices(0);
|
|
|
- for (int i=0;i<num;i++)
|
|
|
- {
|
|
|
- mAudioID = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(i,0), false, &wanted_spec, &spec,0);
|
|
|
- if (mAudioID > 0)
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ VideoPlayer *pointer = (VideoPlayer*)ctx;
|
|
|
|
|
|
- /* 检查实际使用的配置(保存在spec,由SDL_OpenAudio()填充) */
|
|
|
-// if (spec.format != AUDIO_S16SYS)
|
|
|
- if (mAudioID <= 0)
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ if (pointer->mIsOpenStream)
|
|
|
{
|
|
|
- mIsAudioThreadFinished = true;
|
|
|
- return -1;
|
|
|
+ ///打开超时10秒
|
|
|
+ if ((av_gettime()-pointer->mCallStartTime) >= 10000000)
|
|
|
+ {
|
|
|
+ ret = 1;
|
|
|
+ }
|
|
|
}
|
|
|
-fprintf(stderr, "mAudioID=%d\n\n\n\n\n\n", mAudioID);
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-void VideoPlayer::closeSDL()
|
|
|
-{
|
|
|
- if (mAudioID > 0)
|
|
|
+ else
|
|
|
{
|
|
|
- SDL_LockAudioDevice(mAudioID);
|
|
|
- SDL_PauseAudioDevice(mAudioID, 1);
|
|
|
- SDL_UnlockAudioDevice(mAudioID);
|
|
|
-
|
|
|
- SDL_CloseAudioDevice(mAudioID);
|
|
|
+ ///读取超时10秒
|
|
|
+ if ((av_gettime()-pointer->mCallStartTime) >= 10000000)
|
|
|
+ {
|
|
|
+ ret = 1;
|
|
|
+ }
|
|
|
}
|
|
|
+//fprintf(stderr,"%s mIsOpenStream=%d ret=%d \n", __FUNCTION__, pointer->mIsOpenStream, ret);
|
|
|
|
|
|
- mAudioID = 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-void VideoPlayer::readVideoFile()
|
|
|
+void VideoPlayer::run()
|
|
|
{
|
|
|
- ///SDL初始化需要放入子线程中,否则有些电脑会有问题。
|
|
|
- if (SDL_Init(SDL_INIT_AUDIO))
|
|
|
- {
|
|
|
- doOpenSdlFailed(-100);
|
|
|
- fprintf(stderr, "Could not initialize SDL - %s. \n", SDL_GetError());
|
|
|
- return;
|
|
|
- }
|
|
|
+// ///SDL初始化需要放入子线程中,否则有些电脑会有问题。
|
|
|
+// if (SDL_Init(SDL_INIT_AUDIO))
|
|
|
+// {
|
|
|
+// doOpenSdlFailed(-100);
|
|
|
+// fprintf(stderr, "Could not initialize SDL - %s. \n", SDL_GetError());
|
|
|
+// return;
|
|
|
+// }
|
|
|
|
|
|
mIsReadThreadFinished = false;
|
|
|
mIsReadFinished = false;
|
|
|
+ mIsReadError = false;
|
|
|
|
|
|
const char * file_path = mFilePath.c_str();
|
|
|
|
|
@@ -260,13 +302,20 @@ void VideoPlayer::readVideoFile()
|
|
|
//Allocate an AVFormatContext.
|
|
|
pFormatCtx = avformat_alloc_context();
|
|
|
|
|
|
+ pFormatCtx->interrupt_callback.callback = CheckInterrupt;//超时回调
|
|
|
+ pFormatCtx->interrupt_callback.opaque = this;
|
|
|
+
|
|
|
AVDictionary* opts = NULL;
|
|
|
- av_dict_set(&opts, "rtsp_transport", "tcp", 0); //设置tcp or udp,默认一般优先tcp再尝试udp
|
|
|
- av_dict_set(&opts, "stimeout", "60000000", 0);//设置超时3秒
|
|
|
+ av_dict_set(&opts, "rtsp_transport", "udp", 0); //设置tcp or udp,默认一般优先tcp再尝试udp
|
|
|
+// av_dict_set(&opts, "rtsp_transport", "tcp", 0); //设置tcp or udp,默认一般优先tcp再尝试udp
|
|
|
+ av_dict_set(&opts, "stimeout", "5000000", 0);//设置超时5秒
|
|
|
|
|
|
+ mCallStartTime = av_gettime();
|
|
|
+ mIsOpenStream = true;
|
|
|
if (avformat_open_input(&pFormatCtx, file_path, nullptr, &opts) != 0)
|
|
|
{
|
|
|
fprintf(stderr, "can't open the file. \n");
|
|
|
+ mIsReadError = true;
|
|
|
doOpenVideoFileFailed();
|
|
|
goto end;
|
|
|
}
|
|
@@ -274,6 +323,7 @@ void VideoPlayer::readVideoFile()
|
|
|
if (avformat_find_stream_info(pFormatCtx, nullptr) < 0)
|
|
|
{
|
|
|
fprintf(stderr, "Could't find stream infomation.\n");
|
|
|
+ mIsReadError = true;
|
|
|
doOpenVideoFileFailed();
|
|
|
goto end;
|
|
|
}
|
|
@@ -284,11 +334,11 @@ void VideoPlayer::readVideoFile()
|
|
|
///循环查找视频中包含的流信息,
|
|
|
for (int i = 0; i < pFormatCtx->nb_streams; i++)
|
|
|
{
|
|
|
- if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
|
|
+ if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
|
|
{
|
|
|
videoStream = i;
|
|
|
}
|
|
|
- if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audioStream < 0)
|
|
|
+ if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audioStream < 0)
|
|
|
{
|
|
|
audioStream = i;
|
|
|
}
|
|
@@ -299,9 +349,14 @@ void VideoPlayer::readVideoFile()
|
|
|
///打开视频解码器,并启动视频线程
|
|
|
if (videoStream >= 0)
|
|
|
{
|
|
|
+ AVStream *video_stream = pFormatCtx->streams[videoStream];
|
|
|
+
|
|
|
///查找视频解码器
|
|
|
- pCodecCtx = pFormatCtx->streams[videoStream]->codec;
|
|
|
- pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
|
|
|
+ pCodec = (AVCodec*)avcodec_find_decoder(video_stream->codecpar->codec_id);
|
|
|
+ pCodecCtx = avcodec_alloc_context3(pCodec);
|
|
|
+ pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
|
|
|
+
|
|
|
+ avcodec_parameters_to_context(pCodecCtx, video_stream->codecpar);
|
|
|
|
|
|
if (pCodec == nullptr)
|
|
|
{
|
|
@@ -318,7 +373,7 @@ void VideoPlayer::readVideoFile()
|
|
|
goto end;
|
|
|
}
|
|
|
|
|
|
- mVideoStream = pFormatCtx->streams[videoStream];
|
|
|
+ mVideoStream = video_stream;
|
|
|
|
|
|
///创建一个线程专门用来解码视频
|
|
|
std::thread([&](VideoPlayer *pointer)
|
|
@@ -331,9 +386,10 @@ void VideoPlayer::readVideoFile()
|
|
|
|
|
|
if (audioStream >= 0)
|
|
|
{
|
|
|
+ AVStream *audio_stream = pFormatCtx->streams[audioStream];
|
|
|
+
|
|
|
///查找音频解码器
|
|
|
- aCodecCtx = pFormatCtx->streams[audioStream]->codec;
|
|
|
- aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
|
|
|
+ aCodec = (AVCodec*)avcodec_find_decoder(audio_stream->codecpar->codec_id);
|
|
|
|
|
|
if (aCodec == NULL)
|
|
|
{
|
|
@@ -342,6 +398,10 @@ void VideoPlayer::readVideoFile()
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ /* Allocate a codec context for the decoder */
|
|
|
+ aCodecCtx = avcodec_alloc_context3(aCodec);
|
|
|
+ avcodec_parameters_to_context(aCodecCtx, audio_stream->codecpar);
|
|
|
+
|
|
|
///打开音频解码器
|
|
|
if (avcodec_open2(aCodecCtx, aCodec, nullptr) < 0)
|
|
|
{
|
|
@@ -377,13 +437,13 @@ void VideoPlayer::readVideoFile()
|
|
|
//输出的采样格式 16bit PCM
|
|
|
out_sample_fmt = AV_SAMPLE_FMT_S16;
|
|
|
//输入的采样率
|
|
|
- in_sample_rate = aCodecCtx->sample_rate;
|
|
|
+ m_in_sample_rate = aCodecCtx->sample_rate;
|
|
|
//输入的声道布局
|
|
|
in_ch_layout = aCodecCtx->channel_layout;
|
|
|
|
|
|
//输出的采样率
|
|
|
-// out_sample_rate = 44100;
|
|
|
- out_sample_rate = aCodecCtx->sample_rate;
|
|
|
+// m_out_sample_rate = 44100;
|
|
|
+ m_out_sample_rate = aCodecCtx->sample_rate;
|
|
|
|
|
|
//输出的声道布局
|
|
|
|
|
@@ -399,8 +459,8 @@ void VideoPlayer::readVideoFile()
|
|
|
in_ch_layout = av_get_default_channel_layout(aCodecCtx->channels);
|
|
|
}
|
|
|
|
|
|
- swrCtx = swr_alloc_set_opts(nullptr, out_ch_layout, out_sample_fmt, out_sample_rate,
|
|
|
- in_ch_layout, in_sample_fmt, in_sample_rate, 0, nullptr);
|
|
|
+ swrCtx = swr_alloc_set_opts(nullptr, out_ch_layout, out_sample_fmt, m_out_sample_rate,
|
|
|
+ in_ch_layout, in_sample_fmt, m_in_sample_rate, 0, nullptr);
|
|
|
|
|
|
/** Open the resampler with the specified parameters. */
|
|
|
int ret = swr_init(swrCtx);
|
|
@@ -417,7 +477,7 @@ void VideoPlayer::readVideoFile()
|
|
|
}
|
|
|
|
|
|
//存储pcm数据
|
|
|
- int out_linesize = out_sample_rate * audio_tgt_channels;
|
|
|
+ int out_linesize = m_out_sample_rate * audio_tgt_channels;
|
|
|
|
|
|
// out_linesize = av_samples_get_buffer_size(NULL, audio_tgt_channels, av_get_bytes_per_sample(out_sample_fmt), out_sample_fmt, 1);
|
|
|
out_linesize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
|
@@ -425,32 +485,32 @@ void VideoPlayer::readVideoFile()
|
|
|
|
|
|
mAudioStream = pFormatCtx->streams[audioStream];
|
|
|
|
|
|
- ///打开SDL播放声音
|
|
|
- int code = openSDL();
|
|
|
+// ///打开SDL播放声音
|
|
|
+// int code = openSDL();
|
|
|
|
|
|
- if (code == 0)
|
|
|
- {
|
|
|
- SDL_LockAudioDevice(mAudioID);
|
|
|
- SDL_PauseAudioDevice(mAudioID,0);
|
|
|
- SDL_UnlockAudioDevice(mAudioID);
|
|
|
+// if (code == 0)
|
|
|
+// {
|
|
|
+// SDL_LockAudioDevice(mAudioID);
|
|
|
+// SDL_PauseAudioDevice(mAudioID,0);
|
|
|
+// SDL_UnlockAudioDevice(mAudioID);
|
|
|
|
|
|
mIsAudioThreadFinished = false;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- doOpenSdlFailed(code);
|
|
|
- }
|
|
|
+// }
|
|
|
+// else
|
|
|
+// {
|
|
|
+// doOpenSdlFailed(code);
|
|
|
+// }
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-// av_dump_format(pFormatCtx, 0, file_path, 0); //输出视频信息
|
|
|
+ av_dump_format(pFormatCtx, 0, file_path, 0); //输出视频信息
|
|
|
|
|
|
mPlayerState = VideoPlayer_Playing;
|
|
|
doPlayerStateChanged(VideoPlayer_Playing, mVideoStream != nullptr, mAudioStream != nullptr);
|
|
|
|
|
|
mVideoStartTime = av_gettime();
|
|
|
-fprintf(stderr, "%s mIsQuit=%d mIsPause=%d \n", __FUNCTION__, mIsQuit, mIsPause);
|
|
|
+//fprintf(stderr, "%s mIsQuit=%d mIsPause=%d file_path=%s \n", __FUNCTION__, mIsQuit, mIsPause, file_path);
|
|
|
while (1)
|
|
|
{
|
|
|
if (mIsQuit)
|
|
@@ -477,7 +537,7 @@ fprintf(stderr, "%s mIsQuit=%d mIsPause=%d \n", __FUNCTION__, mIsQuit, mIsPause)
|
|
|
|
|
|
if (av_seek_frame(pFormatCtx, stream_index, seek_target, AVSEEK_FLAG_BACKWARD) < 0)
|
|
|
{
|
|
|
- fprintf(stderr, "%s: error while seeking\n",pFormatCtx->filename);
|
|
|
+ fprintf(stderr, "%s: error while seeking\n", file_path);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -531,25 +591,31 @@ fprintf(stderr, "%s mIsQuit=%d mIsPause=%d \n", __FUNCTION__, mIsQuit, mIsPause)
|
|
|
}
|
|
|
|
|
|
AVPacket packet;
|
|
|
+//qDebug("%s av_read_frame .... \n", __FUNCTION__);
|
|
|
+
|
|
|
+ mCallStartTime = av_gettime();
|
|
|
+ mIsOpenStream = false;
|
|
|
+
|
|
|
if (av_read_frame(pFormatCtx, &packet) < 0)
|
|
|
{
|
|
|
mIsReadFinished = true;
|
|
|
-
|
|
|
- if (mIsQuit)
|
|
|
- {
|
|
|
- break; //解码线程也执行完了 可以退出了
|
|
|
- }
|
|
|
+ mIsReadError = true;
|
|
|
+// qDebug("%s av_read_frame failed \n", __FUNCTION__);
|
|
|
+// if (mIsQuit)
|
|
|
+// {
|
|
|
+// break; //解码线程也执行完了 可以退出了
|
|
|
+// }
|
|
|
|
|
|
mSleep(10);
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
+//qDebug("%s mIsQuit=%d mIsPause=%d packet.stream_index=%d \n", __FUNCTION__, mIsQuit, mIsPause, packet.stream_index);
|
|
|
if (packet.stream_index == videoStream)
|
|
|
{
|
|
|
inputVideoQuene(packet);
|
|
|
//这里我们将数据存入队列 因此不调用 av_free_packet 释放
|
|
|
}
|
|
|
- else if( packet.stream_index == audioStream )
|
|
|
+ else if(packet.stream_index == audioStream)
|
|
|
{
|
|
|
if (mIsAudioThreadFinished)
|
|
|
{ ///SDL没有打开,则音频数据直接释放
|
|
@@ -559,6 +625,9 @@ fprintf(stderr, "%s mIsQuit=%d mIsPause=%d \n", __FUNCTION__, mIsQuit, mIsPause)
|
|
|
{
|
|
|
inputAudioQuene(packet);
|
|
|
//这里我们将数据存入队列 因此不调用 av_free_packet 释放
|
|
|
+
|
|
|
+ //音频解码不开线程,因此这里直接调用解码操作
|
|
|
+ decodeAudioFrame(false);
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -583,15 +652,18 @@ end:
|
|
|
|
|
|
if (mPlayerState != VideoPlayer_Stop) //不是外部调用的stop 是正常播放结束
|
|
|
{
|
|
|
- stop();
|
|
|
+ stop(false);
|
|
|
}
|
|
|
|
|
|
+ mIsAudioThreadFinished = true;
|
|
|
while((mVideoStream != nullptr && !mIsVideoThreadFinished) || (mAudioStream != nullptr && !mIsAudioThreadFinished))
|
|
|
{
|
|
|
+fprintf(stderr, "%s:%d mIsVideoThreadFinished=%d mIsAudioThreadFinished=%d \n", __FILE__, __LINE__, mIsVideoThreadFinished, mIsAudioThreadFinished);
|
|
|
mSleep(10);
|
|
|
} //确保视频线程结束后 再销毁队列
|
|
|
|
|
|
- closeSDL();
|
|
|
+// closeSDL();
|
|
|
+ mPcmPlayer->stopPlay();
|
|
|
|
|
|
if (swrCtx != nullptr)
|
|
|
{
|
|
@@ -628,7 +700,14 @@ end:
|
|
|
|
|
|
SDL_Quit();
|
|
|
|
|
|
- doPlayerStateChanged(VideoPlayer_Stop, mVideoStream != nullptr, mAudioStream != nullptr);
|
|
|
+ if (mIsReadError && !mIsQuit)
|
|
|
+ {
|
|
|
+ doPlayerStateChanged(VideoPlayer_ReadError, mVideoStream != nullptr, mAudioStream != nullptr);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ doPlayerStateChanged(VideoPlayer_Stop, mVideoStream != nullptr, mAudioStream != nullptr);
|
|
|
+ }
|
|
|
|
|
|
mIsReadThreadFinished = true;
|
|
|
|
|
@@ -637,10 +716,10 @@ fprintf(stderr, "%s finished \n", __FUNCTION__);
|
|
|
|
|
|
bool VideoPlayer::inputVideoQuene(const AVPacket &pkt)
|
|
|
{
|
|
|
- if (av_dup_packet((AVPacket*)&pkt) < 0)
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
+// if (av_dup_packet((AVPacket*)&pkt) < 0)
|
|
|
+// {
|
|
|
+// return false;
|
|
|
+// }
|
|
|
|
|
|
mConditon_Video->Lock();
|
|
|
mVideoPacktList.push_back(pkt);
|
|
@@ -664,10 +743,10 @@ void VideoPlayer::clearVideoQuene()
|
|
|
|
|
|
bool VideoPlayer::inputAudioQuene(const AVPacket &pkt)
|
|
|
{
|
|
|
- if (av_dup_packet((AVPacket*)&pkt) < 0)
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
+// if (av_dup_packet((AVPacket*)&pkt) < 0)
|
|
|
+// {
|
|
|
+// return false;
|
|
|
+// }
|
|
|
|
|
|
mConditon_Audio->Lock();
|
|
|
mAudioPacktList.push_back(pkt);
|
|
@@ -728,7 +807,7 @@ void VideoPlayer::doTotalTimeChanged(const int64_t &uSec)
|
|
|
///播放器状态改变的时候回调此函数
|
|
|
void VideoPlayer::doPlayerStateChanged(const VideoPlayerState &state, const bool &hasVideo, const bool &hasAudio)
|
|
|
{
|
|
|
- fprintf(stderr, "%s \n", __FUNCTION__);
|
|
|
+ fprintf(stderr, "%s state=%d\n", __FUNCTION__, state);
|
|
|
|
|
|
if (mVideoPlayerCallBack != nullptr)
|
|
|
{
|
|
@@ -740,7 +819,7 @@ void VideoPlayer::doPlayerStateChanged(const VideoPlayerState &state, const bool
|
|
|
///显示视频数据,此函数不宜做耗时操作,否则会影响播放的流畅性。
|
|
|
void VideoPlayer::doDisplayVideo(const uint8_t *yuv420Buffer, const int &width, const int &height)
|
|
|
{
|
|
|
-// fprintf(stderr, "%s \n", __FUNCTION__);
|
|
|
+// fprintf(stderr, "%s width=%d height=%d \n", __FUNCTION__, width, height);
|
|
|
if (mVideoPlayerCallBack != nullptr)
|
|
|
{
|
|
|
VideoFramePtr videoFrame = std::make_shared<VideoFrame>();
|