|
@@ -186,7 +186,7 @@ void VideoPlayer::decodeAudioThread()
|
|
|
seek_flag_audio = 0;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+#ifdef USE_PCM_PLAYER
|
|
|
///直播流为了保证降低延迟,当音频播放队列过大时,会提高播放的采样率
|
|
|
///因此,非直播流,不能一次性把所有音频塞入队列,需要限制播放队列中的数据量
|
|
|
if (!m_is_live_mode)
|
|
@@ -196,7 +196,7 @@ void VideoPlayer::decodeAudioThread()
|
|
|
mSleep(5);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+#endif
|
|
|
//解码AVPacket->AVFrame
|
|
|
if (int ret = avcodec_send_packet(aCodecCtx, packet) && ret != 0)
|
|
|
{
|
|
@@ -294,7 +294,7 @@ void VideoPlayer::decodeAudioThread()
|
|
|
PCMFramePtr pcmFramePtr = std::make_shared<PCMFrame>();
|
|
|
pcmFramePtr->setFrameBuffer(audio_buf, resampled_data_size);
|
|
|
pcmFramePtr->setFrameInfo(m_out_sample_rate, audio_tgt_channels, pts_ms);
|
|
|
-
|
|
|
+#ifdef USE_PCM_PLAYER
|
|
|
int audio_frame_size = m_pcm_player->inputPCMFrame(pcmFramePtr);
|
|
|
|
|
|
if (audio_frame_size > 0) //大于0 表示音频播放设备处于打开状态
|
|
@@ -302,7 +302,7 @@ void VideoPlayer::decodeAudioThread()
|
|
|
// std::lock_guard<std::mutex> lck(m_mutex_audio_clk);
|
|
|
audio_clock = m_pcm_player->getCurrentPts();
|
|
|
}
|
|
|
-
|
|
|
+#endif
|
|
|
// std::cout<<resampled_data_size<<" "<<audio_frame_size<<" "<<audio_clock<<" "<<pts_ms<<std::endl;
|
|
|
}
|
|
|
}
|
|
@@ -310,205 +310,13 @@ void VideoPlayer::decodeAudioThread()
|
|
|
|
|
|
av_packet_unref(packet);
|
|
|
}
|
|
|
-
|
|
|
+#ifdef USE_PCM_PLAYER
|
|
|
///等待播放完成
|
|
|
while (m_pcm_player->getPcmFrameSize() > 0)
|
|
|
{
|
|
|
mSleep(5);
|
|
|
}
|
|
|
-
|
|
|
+#endif
|
|
|
mIsAudioThreadFinished = true;
|
|
|
fprintf(stderr, "%s finished \n", __FUNCTION__);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-// int VideoPlayer::decodeAudioFrame(bool isBlock)
|
|
|
-// {
|
|
|
-// int audioBufferSize = 0;
|
|
|
-// float pts_s = 0.0f; //时间戳(秒)
|
|
|
-
|
|
|
-// while(1)
|
|
|
-// {
|
|
|
-// if (mIsQuit)
|
|
|
-// {
|
|
|
-// mIsAudioThreadFinished = true;
|
|
|
-// clearAudioQuene(); //清空队列
|
|
|
-// break;
|
|
|
-// }
|
|
|
-
|
|
|
-// if (mIsPause == true) //判断暂停
|
|
|
-// {
|
|
|
-// break;
|
|
|
-// }
|
|
|
-
|
|
|
-// mConditon_Audio->Lock();
|
|
|
-// int audio_list_size = mAudioPacktList.size();
|
|
|
-// //fprintf(stderr, "mAudioPacktList.size()=%d \n", audio_list_size);
|
|
|
-// // if (mAudioPacktList.size() <= 0)
|
|
|
-// // {
|
|
|
-// // if (isBlock)
|
|
|
-// // {
|
|
|
-// // mConditon_Audio->Wait();
|
|
|
-// // }
|
|
|
-// // else
|
|
|
-// // {
|
|
|
-// // mConditon_Audio->Unlock();
|
|
|
-// // break;
|
|
|
-// // }
|
|
|
-// // }
|
|
|
-
|
|
|
-// AVPacket packet = mAudioPacktList.front();
|
|
|
-// mAudioPacktList.pop_front();
|
|
|
-// //qDebug()<<__FUNCTION__<<mAudioPacktList.size();
|
|
|
-// mConditon_Audio->Unlock();
|
|
|
-
|
|
|
-// AVPacket *pkt = &packet;
|
|
|
-
|
|
|
-// /* if update, update the audio clock w/pts */
|
|
|
-// if (packet->pts != AV_NOPTS_VALUE)
|
|
|
-// {
|
|
|
-// pts_s = av_q2d(mAudioStream->time_base) * packet->pts;
|
|
|
-// }
|
|
|
-
|
|
|
-// //收到这个数据 说明刚刚执行过跳转 现在需要把解码器的数据 清除一下
|
|
|
-// if(strcmp((char*)packet->data,FLUSH_DATA) == 0)
|
|
|
-// {
|
|
|
-// avcodec_flush_buffers(aCodecCtx);
|
|
|
-// av_packet_unref(pkt);
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-
|
|
|
-// if (seek_flag_audio)
|
|
|
-// {
|
|
|
-// //发生了跳转 则跳过关键帧到目的时间的这几帧
|
|
|
-// if (pts_s < seek_time)
|
|
|
-// {
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-// else
|
|
|
-// {
|
|
|
-// seek_flag_audio = 0;
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// int got_frame = 0;
|
|
|
-
|
|
|
-// //解码AVPacket->AVFrame
|
|
|
-// if (int ret = avcodec_send_packet(aCodecCtx, &packet) && ret != 0)
|
|
|
-// {
|
|
|
-// char buffer[1024] = {0};
|
|
|
-// av_strerror(ret, buffer, 1024);
|
|
|
-// fprintf(stderr, "input AVPacket to decoder failed! ret = %d %s\n", ret, buffer);
|
|
|
-// }
|
|
|
-// else
|
|
|
-// {
|
|
|
-// while(1)
|
|
|
-// {
|
|
|
-// int ret = avcodec_receive_frame(aCodecCtx, aFrame);
|
|
|
-// if (ret != 0)
|
|
|
-// {
|
|
|
-// // char buffer[1024] = {0};
|
|
|
-// // av_strerror(ret, buffer, 1024);
|
|
|
-// // fprintf(stderr, "avcodec_receive_frame = %d %s\n", ret, buffer);
|
|
|
-// break;
|
|
|
-// }
|
|
|
-
|
|
|
-// /* if update, update the audio clock w/pts */
|
|
|
-// if (packet.pts != AV_NOPTS_VALUE)
|
|
|
-// {
|
|
|
-// audio_clock = 1000 * av_q2d(mAudioStream->time_base) * packet.pts;
|
|
|
-// }
|
|
|
-
|
|
|
-// int out_sample_rate = m_out_sample_rate;
|
|
|
-
|
|
|
-// /// ffmpeg解码之后得到的音频数据不是SDL想要的,
|
|
|
-// /// 因此这里需要重采样成44100 双声道 AV_SAMPLE_FMT_S16
|
|
|
-
|
|
|
-// /// 需要保证重采样后音频的时间是相同的,不同采样率下同样时间采集的数据采样点个数肯定不一样。
|
|
|
-// /// 因此就需要重新计算采样点个数(使用下面的函数)
|
|
|
-// /// 将in_sample_rate的采样次数换算成out_sample_rate对应的采样次数
|
|
|
-// int nb_samples = av_rescale_rnd(swr_get_delay(swrCtx, out_sample_rate) + aFrame->nb_samples, out_sample_rate, m_in_sample_rate, AV_ROUND_UP);
|
|
|
-// //qDebug()<<swr_get_delay(swrCtx, out_sample_rate) + aFrame->nb_samples<<aFrame->nb_samples<<nb_samples;
|
|
|
-// // int nb_samples = av_rescale_rnd(aFrame->nb_samples, out_sample_rate, m_in_sample_rate, AV_ROUND_INF);
|
|
|
-// if (aFrame_ReSample != nullptr)
|
|
|
-// {
|
|
|
-// if (aFrame_ReSample->nb_samples != nb_samples || aFrame_ReSample->sample_rate != out_sample_rate)
|
|
|
-// {
|
|
|
-// av_frame_free(&aFrame_ReSample);
|
|
|
-// aFrame_ReSample = nullptr;
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// ///解码一帧后才能获取到采样率等信息,因此将初始化放到这里
|
|
|
-// if (aFrame_ReSample == nullptr)
|
|
|
-// {
|
|
|
-// aFrame_ReSample = av_frame_alloc();
|
|
|
-
|
|
|
-// aFrame_ReSample->format = out_sample_fmt;
|
|
|
-// aFrame_ReSample->channel_layout = out_ch_layout;
|
|
|
-// aFrame_ReSample->sample_rate = out_sample_rate;
|
|
|
-// aFrame_ReSample->nb_samples = nb_samples;
|
|
|
-
|
|
|
-// int ret = av_samples_fill_arrays(aFrame_ReSample->data, aFrame_ReSample->linesize, audio_buf, audio_tgt_channels, aFrame_ReSample->nb_samples, out_sample_fmt, 0);
|
|
|
-// // int ret = av_frame_get_buffer(aFrame_ReSample, 0);
|
|
|
-// if (ret < 0)
|
|
|
-// {
|
|
|
-// fprintf(stderr, "Error allocating an audio buffer\n");
|
|
|
-// // exit(1);
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// ///2024-09-16
|
|
|
-// //当重采样的采样率不一致的时候,原先的方法会存在杂音问题,解决方法如下:
|
|
|
-// // 1) 如果没有提供足够的空间用于保存输出数据,采样数据会缓存在swr中。可以通过 swr_get_out_samples()来获取下一次调用swr_convert在给定输入样本数量下输出样本数量的上限,来提供足够的空间。
|
|
|
-// // 2)如果是采样频率转换,转换完成后采样数据可能会缓存在swr中,它希望你能给它更多的输入数据。
|
|
|
-// // 3)如果实际上并不需要更多输入数据,通过调用swr_convert(),其中参数in_count设置为0来获取缓存在swr中的数据。
|
|
|
-// // 4)转换结束之后需要冲刷swr_context的缓冲区,通过调用swr_convert(),其中参数in设置为NULL,参数in_count设置为0。
|
|
|
-// for(int i=0;i<2;i++)
|
|
|
-// {
|
|
|
-// ///执行重采样
|
|
|
-// int len2;
|
|
|
-
|
|
|
-// if (i == 0)
|
|
|
-// {
|
|
|
-// len2 = swr_convert(swrCtx, aFrame_ReSample->data, aFrame_ReSample->nb_samples, (const uint8_t**)aFrame->data, aFrame->nb_samples);
|
|
|
-// }
|
|
|
-// else
|
|
|
-// {
|
|
|
-// len2 = swr_convert(swrCtx, aFrame_ReSample->data, aFrame_ReSample->nb_samples, NULL, 0);
|
|
|
-// }
|
|
|
-
|
|
|
-// if (len2 <= 0)
|
|
|
-// {
|
|
|
-// break;
|
|
|
-// }
|
|
|
-
|
|
|
-// ///必须根据swr_convert实际返回的值计算数据大小
|
|
|
-// int resampled_data_size = len2 * audio_tgt_channels * av_get_bytes_per_sample(out_sample_fmt);
|
|
|
-// int OneChannelDataSize = resampled_data_size / audio_tgt_channels;
|
|
|
-
|
|
|
-// audioBufferSize = resampled_data_size;
|
|
|
-
|
|
|
-// PCMFramePtr pcmFramePtr = std::make_shared<PCMFrame>();
|
|
|
-// pcmFramePtr->setFrameBuffer(audio_buf, resampled_data_size);
|
|
|
-// pcmFramePtr->setFrameInfo(m_out_sample_rate, audio_tgt_channels, pts_s*1000);
|
|
|
-
|
|
|
-// int audio_frame_size = m_pcm_player->inputPCMFrame(pcmFramePtr);
|
|
|
-// //qDebug()<<resampled_data_size<<audio_frame_size;
|
|
|
-// audio_clock = m_pcm_player->getCurrentPts() / 1000.0;
|
|
|
-// }
|
|
|
-
|
|
|
-// got_frame = 1;
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// av_packet_unref(&packet);
|
|
|
-
|
|
|
-// if (got_frame)
|
|
|
-// {
|
|
|
-// break;
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// return audioBufferSize;
|
|
|
-// }
|