|
@@ -11,6 +11,47 @@
|
|
|
#include <iostream>
|
|
|
#include <stdio.h>
|
|
|
|
|
|
+static void addADTStoPacket(uint8_t* packet, int packetLen, int channel, int sample_rate)
|
|
|
+{
|
|
|
+ int profile = 2; //AAC LC,MediaCodecInfo.CodecProfileLevel.AACObjectLC;
|
|
|
+ int freqIdx = 8; //16K, 见后面注释avpriv_mpeg4audio_sample_rates中32000对应的数组下标,来自ffmpeg源码
|
|
|
+ int chanCfg = channel; //见后面注释channel_configuration,Stero双声道立体声
|
|
|
+
|
|
|
+ int avpriv_mpeg4audio_sample_rates[] = {
|
|
|
+ 96000, 88200, 64000, 48000, 44100, 32000,
|
|
|
+ 24000, 22050, 16000, 12000, 11025, 8000, 7350
|
|
|
+ };
|
|
|
+ /*channel_configuration: 表示声道数chanCfg
|
|
|
+ 0: Defined in AOT Specifc Config
|
|
|
+ 1: 1 channel: front-center
|
|
|
+ 2: 2 channels: front-left, front-right
|
|
|
+ 3: 3 channels: front-center, front-left, front-right
|
|
|
+ 4: 4 channels: front-center, front-left, front-right, back-center
|
|
|
+ 5: 5 channels: front-center, front-left, front-right, back-left, back-right
|
|
|
+ 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
|
|
|
+ 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
|
|
|
+ 8-15: Reserved
|
|
|
+ */
|
|
|
+
|
|
|
+ for (int i=0; i<13; i++)
|
|
|
+ {
|
|
|
+ if (avpriv_mpeg4audio_sample_rates[i] == sample_rate)
|
|
|
+ {
|
|
|
+ freqIdx = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // fill in ADTS data
|
|
|
+ packet[0] = (uint8_t)0xFF;
|
|
|
+ packet[1] = (uint8_t)0xF9;
|
|
|
+ packet[2] = (uint8_t)(((profile-1)<<6) + (freqIdx<<2) +(chanCfg>>2));
|
|
|
+ packet[3] = (uint8_t)(((chanCfg&3)<<6) + (packetLen>>11));
|
|
|
+ packet[4] = (uint8_t)((packetLen&0x7FF) >> 3);
|
|
|
+ packet[5] = (uint8_t)(((packetLen&7)<<5) + 0x1F);
|
|
|
+ packet[6] = (uint8_t)0xFC;
|
|
|
+}
|
|
|
+
|
|
|
void VideoPlayer::decodeAudioThread()
|
|
|
{
|
|
|
fprintf(stderr, "%s start \n", __FUNCTION__);
|
|
@@ -47,23 +88,89 @@ void VideoPlayer::decodeAudioThread()
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- AVPacket packet = m_audio_pkt_list.front();
|
|
|
+ AVPacket pkt = m_audio_pkt_list.front();
|
|
|
m_audio_pkt_list.pop_front();
|
|
|
lck.unlock();
|
|
|
|
|
|
- AVPacket *pkt = &packet;
|
|
|
+ AVPacket *packet = &pkt;
|
|
|
|
|
|
/* if update, update the audio clock w/pts */
|
|
|
- if (pkt->pts != AV_NOPTS_VALUE)
|
|
|
+ if (packet->pts != AV_NOPTS_VALUE)
|
|
|
+ {
|
|
|
+ pts_ms = av_q2d(mAudioStream->time_base) * packet->pts * 1000;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!m_enable_audio_play) //音频播放未启用,则把音频同步到外部时钟
|
|
|
+ {
|
|
|
+ int64_t audio_pts = 0; //音频pts
|
|
|
+ if (packet->dts != AV_NOPTS_VALUE)
|
|
|
+ {
|
|
|
+ audio_pts = packet->dts;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ audio_pts = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (audio_pts < 0)
|
|
|
+ {
|
|
|
+ audio_pts = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ audio_pts *= av_q2d(mAudioStream->time_base) * m_speed * 1000;
|
|
|
+ audio_clock = audio_pts;
|
|
|
+ ///音频同步到外部时钟
|
|
|
+ uint64_t realTime = 0;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ mSleep(5);
|
|
|
+ realTime = (av_gettime() - mVideoStartTime) * m_speed / 1000; //毫秒
|
|
|
+ }while(!m_is_stop && audio_pts > (realTime-10));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m_event_handle && m_enable_encoded_audio_callback)
|
|
|
{
|
|
|
- pts_ms = av_q2d(mAudioStream->time_base) * pkt->pts * 1000;
|
|
|
+ // printf("%s:%d mAudioStream->codecpar->codec_id=%d %d\n", __FILE__, __LINE__, mAudioStream->codecpar->codec_id, AV_CODEC_ID_AAC);
|
|
|
+ if (mAudioStream->codecpar->codec_id == AV_CODEC_ID_AAC)
|
|
|
+ {
|
|
|
+ //回调AAC数据
|
|
|
+ uint8_t adtsBuffer[7] = {0};
|
|
|
+ addADTStoPacket(adtsBuffer, 7 + packet->size, aCodecCtx->channels, aCodecCtx->sample_rate);
|
|
|
+
|
|
|
+ AACFramePtr aac_frame = std::make_shared<AACFrame>();
|
|
|
+ aac_frame->setFrameBuffer(adtsBuffer, 7, packet->data, packet->size);
|
|
|
+
|
|
|
+ m_event_handle->onAudioBuffer(aac_frame);
|
|
|
+ }
|
|
|
+ else if(mAudioStream->codecpar->codec_id == AV_CODEC_ID_PCM_MULAW)
|
|
|
+ {
|
|
|
+ //回调PCMU数据
|
|
|
+ PCMFramePtr audio_frame = std::make_shared<PCMFrame>();
|
|
|
+ audio_frame->setFrameBuffer(packet->data, packet->size);
|
|
|
+ audio_frame->setFrameInfo(aCodecCtx->sample_rate, aCodecCtx->channels, audio_clock, PCMFrame::PCMFRAME_TYPE_PCMU);
|
|
|
+ m_event_handle->onAudioBuffer(audio_frame);
|
|
|
+ }
|
|
|
+ else if(mAudioStream->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW)
|
|
|
+ {
|
|
|
+ //回调PCMA数据
|
|
|
+ PCMFramePtr audio_frame = std::make_shared<PCMFrame>();
|
|
|
+ audio_frame->setFrameBuffer(packet->data, packet->size);
|
|
|
+ audio_frame->setFrameInfo(aCodecCtx->sample_rate, aCodecCtx->channels, audio_clock, PCMFrame::PCMFRAME_TYPE_PCMA);
|
|
|
+ m_event_handle->onAudioBuffer(audio_frame);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!m_enable_audio_play)
|
|
|
+ {
|
|
|
+ av_packet_unref(packet);
|
|
|
+ continue;
|
|
|
}
|
|
|
|
|
|
//收到这个数据 说明刚刚执行过跳转 现在需要把解码器的数据 清除一下
|
|
|
- if(strcmp((char*)pkt->data,FLUSH_DATA) == 0)
|
|
|
+ if(strcmp((char*)packet->data,FLUSH_DATA) == 0)
|
|
|
{
|
|
|
avcodec_flush_buffers(aCodecCtx);
|
|
|
- av_packet_unref(pkt);
|
|
|
+ av_packet_unref(packet);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -91,7 +198,7 @@ void VideoPlayer::decodeAudioThread()
|
|
|
}
|
|
|
|
|
|
//解码AVPacket->AVFrame
|
|
|
- if (int ret = avcodec_send_packet(aCodecCtx, &packet) && ret != 0)
|
|
|
+ if (int ret = avcodec_send_packet(aCodecCtx, packet) && ret != 0)
|
|
|
{
|
|
|
char buffer[1024] = {0};
|
|
|
av_strerror(ret, buffer, 1024);
|
|
@@ -198,11 +305,10 @@ void VideoPlayer::decodeAudioThread()
|
|
|
|
|
|
// std::cout<<resampled_data_size<<" "<<audio_frame_size<<" "<<audio_clock<<" "<<pts_ms<<std::endl;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- av_packet_unref(&packet);
|
|
|
+ av_packet_unref(packet);
|
|
|
}
|
|
|
|
|
|
///等待播放完成
|
|
@@ -259,13 +365,13 @@ void VideoPlayer::decodeAudioThread()
|
|
|
// AVPacket *pkt = &packet;
|
|
|
|
|
|
// /* if update, update the audio clock w/pts */
|
|
|
-// if (pkt->pts != AV_NOPTS_VALUE)
|
|
|
+// if (packet->pts != AV_NOPTS_VALUE)
|
|
|
// {
|
|
|
-// pts_s = av_q2d(mAudioStream->time_base) * pkt->pts;
|
|
|
+// pts_s = av_q2d(mAudioStream->time_base) * packet->pts;
|
|
|
// }
|
|
|
|
|
|
// //收到这个数据 说明刚刚执行过跳转 现在需要把解码器的数据 清除一下
|
|
|
-// if(strcmp((char*)pkt->data,FLUSH_DATA) == 0)
|
|
|
+// if(strcmp((char*)packet->data,FLUSH_DATA) == 0)
|
|
|
// {
|
|
|
// avcodec_flush_buffers(aCodecCtx);
|
|
|
// av_packet_unref(pkt);
|