File indexing completed on 2024-06-16 04:38:30
0001 /* 0002 SPDX-FileCopyrightText: 2003 Fabrice Bellard 0003 SPDX-FileCopyrightText: 2020-2022 Mladen Milinkovic <max@smoothware.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "videodecoder.h" 0009 0010 #include "videoplayer/backend/ffplayer.h" 0011 #include "videoplayer/backend/videostate.h" 0012 0013 extern "C" { 0014 #include "libavutil/rational.h" 0015 } 0016 0017 using namespace SubtitleComposer; 0018 0019 VideoDecoder::VideoDecoder(VideoState *state, QObject *parent) 0020 : Decoder(parent), 0021 m_vs(state), 0022 m_timeBase(0.), 0023 m_frameDropsEarly(0) 0024 { 0025 } 0026 0027 int 0028 VideoDecoder::getVideoFrame(AVFrame *frame) 0029 { 0030 const int gotPicture = decodeFrame(frame, nullptr); 0031 if(gotPicture <= 0) 0032 return gotPicture; 0033 0034 frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(m_vs->fmtContext, m_vs->vidStream, frame); 0035 0036 if(frame->pts != AV_NOPTS_VALUE) { 0037 const double dPts = m_timeBase * frame->pts; 0038 if(m_vs->seekDecoder > 0. && !std::isnan(dPts) && m_vs->seekDecoder > dPts) { 0039 m_frameDropsEarly++; 0040 av_frame_unref(frame); 0041 return 0; 0042 } 0043 if(m_vs->framedrop > 0 || (m_vs->framedrop && m_vs->masterSyncType() != AV_SYNC_VIDEO_MASTER)) { 0044 const double diff = dPts - m_vs->masterTime(); 0045 if(!std::isnan(diff) && diff < 0 && fabs(diff) < AV_NOSYNC_THRESHOLD 0046 && pktSerial() == m_vs->vidClk.serial() && m_queue->nbPackets()) { 0047 m_frameDropsEarly++; 0048 av_frame_unref(frame); 0049 return 0; 0050 } 0051 } 0052 } 0053 0054 return gotPicture; 0055 } 0056 0057 int 0058 VideoDecoder::queuePicture(AVFrame *srcFrame, double pts, double duration, int64_t pos, int serial) 0059 { 0060 #if defined(DEBUG_SYNC) 0061 printf("frame_type=%c pts=%0.3f\n", av_get_picture_type_char(src_frame->pict_type), pts); 0062 #endif 0063 0064 Frame *vp = m_frameQueue->peekWritable(); 0065 if(!vp) 0066 return -1; 0067 0068 vp->sar = srcFrame->sample_aspect_ratio; 0069 vp->uploaded = false; 0070 0071 vp->width = srcFrame->width; 0072 vp->height = srcFrame->height; 0073 vp->format = srcFrame->format; 0074 0075 vp->pts = pts; 0076 vp->duration = duration; 0077 vp->pos = pos; 0078 vp->serial = serial; 0079 0080 av_frame_move_ref(vp->frame, srcFrame); 0081 m_frameQueue->push(); 0082 return 0; 0083 } 0084 0085 void 0086 VideoDecoder::run() 0087 { 0088 AVFrame *frame = av_frame_alloc(); 0089 m_timeBase = av_q2d(m_vs->vidStream->time_base); 0090 0091 if(!frame) 0092 return; 0093 0094 const AVRational fps = av_guess_frame_rate(m_vs->fmtContext, m_vs->vidStream, nullptr); 0095 const double frameDuration = fps.num ? double(fps.den) / fps.num : 0.0; 0096 0097 for(;;) { 0098 int ret = getVideoFrame(frame); 0099 if(ret < 0) 0100 break; 0101 if(!ret) 0102 continue; 0103 0104 double pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * m_timeBase; 0105 ret = queuePicture(frame, pts, frameDuration, frame->pkt_pos, pktSerial()); 0106 av_frame_unref(frame); 0107 0108 if(ret < 0) 0109 break; 0110 } 0111 0112 av_frame_free(&frame); 0113 }