voidRender::slotRender()
{
autovideoCodecCtx=dataInfo->getVideoCtx();
autoaudioCodecCtx=dataInfo->getAudioCtx();
intSDLFormat=dataInfo->getSDLFmt();
intaudioIndex=dataInfo->getAudioIndex();
floatspeed= (dataInfo->getPlaySpeed() ==PLAY_SLOW) ?0.5 : dataInfo->getPlaySpeed();
intisOpenAudio=-1;
if (audioIndex>=0) {
SDL_AudioSpecaudioSpec;
audioSpec.freq=audioCodecCtx->sample_rate; audioSpec.format=SDLFormat; audioSpec.channels=audioCodecCtx->ch_layout.nb_channels; audioSpec.silence=0; audioSpec.samples=audioCodecCtx->frame_size; audioSpec.callback=playAudioCallback; audioSpec.userdata=dataInfo;
isOpenAudio=SDL_OpenAudio(&audioSpec, nullptr);
if (speed==1)
SDL_PauseAudio(0);
}
SDL_Renderer*SDLRend=SDL_CreateRenderer(dataInfo->getSDLWind(), -1, SDL_RENDERER_ACCELERATED);
if (!SDLRend) {
qDebug() <<"SDL_CreateRenderer fail";
}
SDL_Texture*SDLText=SDL_CreateTexture(SDLRend, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, videoCodecCtx->width, videoCodecCtx->height);
if (!SDLText) {
qDebug() <<"SDL_CreateTexture fail";
}
int64_tlastPtsTime=0;
int64_tlastRenderTime=av_gettime();
int64_taudioClock=0;
while (dataInfo->getDecodeState() ||!dataInfo->videoIsEmpty() ||!dataInfo->audioIsEmpty()) {
if (dataInfo->getPlayState() ==PLAY_STOP) {
break;
}
if (dataInfo->videoIsEmpty() &&dataInfo->audioIsEmpty()) {
QThread::msleep(5);
continue;
}
if (dataInfo->videoIsEmpty()) {
QThread::msleep(10);
continue;
}
autovideoData=dataInfo->videoPop();
if (videoData.ptsTime==-1)
continue;
speed= (dataInfo->getPlaySpeed() ==PLAY_SLOW) ?0.5 : dataInfo->getPlaySpeed();
if (dataInfo->getSeekFlag()) {
dataInfo->setSeekFlag(false);
dataInfo->setAudioClock(0);
} else {
if (lastPtsTime!=0&&videoData.ptsTime!=0) {
if (isOpenAudio>=0&&dataInfo->getAudioIndex() >=0&&speed==1) {
if (SDL_GetAudioStatus() ==SDL_AUDIO_PAUSED){
SDL_PauseAudio(0);
}
audioClock=dataInfo->getAudioClock();
if (videoData.ptsTime<audioClock) {
if (audioClock-videoData.ptsTime>=500) { qDebug() <<"丢帧:"<<videoData.ptsTime;
emitsignalProgress(videoData.ptsTime);
lastPtsTime=videoData.ptsTime;
av_frame_free(&videoData.frame);
continue;
}
} else {
while (dataInfo->getPlayState() ==PLAY_PLAY&&!dataInfo->audioIsEmpty()
&&videoData.ptsTime>dataInfo->getAudioClock() &&!dataInfo->getSeekFlag()) {
QThread::msleep(1);
}
}
} else {
if (dataInfo->getAudioIndex() >=0) {
if (SDL_GetAudioStatus() ==SDL_AUDIO_PLAYING)
SDL_PauseAudio(1);
autoaudioData=dataInfo->audioFirst();
while (audioData.ptsTime>=0&&audioData.ptsTime<videoData.ptsTime) {
autotempData=dataInfo->audioPop();
av_free(tempData.buff);
audioData=dataInfo->audioFirst();
dataInfo->setAudioClock(audioData.ptsTime);
}
}
int64_toffset= (videoData.ptsTime-lastPtsTime) *1000.0/speed;
int64_tnowOffset=av_gettime() -lastRenderTime;
if (offset<nowOffset) {
if (nowOffset-offset>=offset) { qDebug() <<"丢帧:"<<videoData.ptsTime;
emitsignalProgress(videoData.ptsTime);
lastPtsTime=videoData.ptsTime;
lastRenderTime=av_gettime();
av_frame_free(&videoData.frame);
continue;
}
} else {
if (offset>nowOffset+1000)
QThread::usleep(offset-nowOffset-1000);
}
}
}
}
SDL_UpdateYUVTexture(SDLText,
nullptr,
videoData.frame->data[0],
videoData.frame->linesize[0],
videoData.frame->data[1],
videoData.frame->linesize[1],
videoData.frame->data[2],
videoData.frame->linesize[2]);
SDL_RenderClear(SDLRend);
SDL_RenderCopy(SDLRend, SDLText, nullptr, nullptr);
SDL_RenderPresent(SDLRend);
lastPtsTime=videoData.ptsTime;
lastRenderTime=av_gettime();
dataInfo->setPlayTime(videoData.ptsTime);
emitsignalProgress(videoData.ptsTime);
while (dataInfo->getPlayState() ==PLAY_PAUSE) {
if (dataInfo->getAudioIndex() >=0)
if (SDL_GetAudioStatus() ==SDL_AUDIO_PLAYING)
SDL_PauseAudio(1);
QThread::msleep(10);
SDL_UpdateYUVTexture(SDLText,
nullptr,
videoData.frame->data[0],
videoData.frame->linesize[0],
videoData.frame->data[1],
videoData.frame->linesize[1],
videoData.frame->data[2],
videoData.frame->linesize[2]);
SDL_RenderClear(SDLRend);
SDL_RenderCopy(SDLRend, SDLText, nullptr, nullptr);
SDL_RenderPresent(SDLRend);
}
av_frame_free(&videoData.frame);
if (dataInfo->getAudioIndex() >=0) {
if (SDL_GetAudioStatus() ==SDL_AUDIO_PAUSED)
SDL_PauseAudio(0);
}
}
if (dataInfo->getAudioIndex() >=0)
SDL_CloseAudio();
SDL_DestroyTexture(SDLText);
SDL_DestroyRenderer(SDLRend);
emitsignalPlayStop();
}
voidRender::playAudioCallback(void*udata, uchar*stream, intlen)
{
SDL_memset(stream, 0, len);
autodataInfo= (DataInfo*)udata;
intSDLFormat=dataInfo->getSDLFmt();
autodata=dataInfo->audioPop();
if (data.ptsTime>0) {
dataInfo->setAudioClock(data.ptsTime);
if (data.buffSize>0)
SDL_MixAudioFormat(stream, data.buff, SDLFormat, data.buffSize, dataInfo->getPlayVolume());
av_free(data.buff);
}
}