File indexing completed on 2024-06-16 04:38:28

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 "decoder.h"
0009 
0010 #include "videoplayer/backend/ffplayer.h"
0011 #include "videoplayer/backend/packetqueue.h"
0012 #include "videoplayer/backend/framequeue.h"
0013 
0014 #include <QWaitCondition>
0015 
0016 
0017 using namespace SubtitleComposer;
0018 
0019 Decoder::Decoder(QObject *parent)
0020     : QThread(parent),
0021       m_reorderPts(-1),
0022       m_pkt(nullptr),
0023       m_queue(nullptr),
0024       m_frameQueue(nullptr),
0025       m_avCtx(nullptr),
0026       m_pktSerial(0),
0027       m_finished(0),
0028       m_emptyQueueCond(nullptr),
0029       m_startPts(0)
0030 {
0031     memset(&m_pkt, 0, sizeof(m_pkt));
0032 }
0033 
0034 void
0035 Decoder::init(AVCodecContext *avctx, PacketQueue *pq, FrameQueue *fq, QWaitCondition *emptyQueueCond)
0036 {
0037     m_queue = pq;
0038     m_frameQueue = fq;
0039     m_avCtx = avctx;
0040     m_pktSerial = -1;
0041     m_finished = 0;
0042     av_packet_free(&m_pkt);
0043     m_emptyQueueCond = emptyQueueCond;
0044     m_startPts = AV_NOPTS_VALUE;
0045 }
0046 
0047 void
0048 Decoder::start()
0049 {
0050     m_queue->start();
0051     QThread::start();
0052 }
0053 
0054 int
0055 Decoder::decodeFrame(AVFrame *frame, AVSubtitle *sub)
0056 {
0057     int ret = AVERROR(EAGAIN);
0058 
0059     for(;;) {
0060         if(m_queue->m_serial == m_pktSerial) {
0061             do {
0062                 if(m_queue->m_abortRequest)
0063                     return -1;
0064 
0065                 switch(m_avCtx->codec_type) {
0066                 case AVMEDIA_TYPE_VIDEO:
0067                     ret = avcodec_receive_frame(m_avCtx, frame);
0068                     if(ret >= 0) {
0069                         if(m_reorderPts == -1)
0070                             frame->pts = frame->best_effort_timestamp;
0071                         else if(!m_reorderPts)
0072                             frame->pts = frame->pkt_dts;
0073                     }
0074                     break;
0075                 case AVMEDIA_TYPE_AUDIO:
0076                     ret = avcodec_receive_frame(m_avCtx, frame);
0077                     if(ret >= 0) {
0078                         AVRational tb = AVRational{ 1, frame->sample_rate };
0079                         if(frame->pts != AV_NOPTS_VALUE)
0080                             frame->pts = av_rescale_q(frame->pts, m_avCtx->pkt_timebase, tb);
0081                         else if(m_nextPts != AV_NOPTS_VALUE)
0082                             frame->pts = av_rescale_q(m_nextPts, m_nextPtsTb, tb);
0083                         if(frame->pts != AV_NOPTS_VALUE) {
0084                             m_nextPts = frame->pts + frame->nb_samples;
0085                             m_nextPtsTb = tb;
0086                         }
0087                     }
0088                     break;
0089                 default:
0090                     break;
0091                 }
0092                 if(ret == AVERROR_EOF) {
0093                     m_finished = m_pktSerial;
0094                     avcodec_flush_buffers(m_avCtx);
0095                     return 0;
0096                 }
0097                 if(ret >= 0)
0098                     return 1;
0099             } while(ret != AVERROR(EAGAIN));
0100         }
0101 
0102         AVPacket *pkt = nullptr;
0103         for(;;) {
0104             if(m_queue->m_nbPackets == 0)
0105                 m_emptyQueueCond->wakeOne();
0106             if(m_pkt) {
0107                 pkt = m_pkt;
0108                 m_pkt = nullptr;
0109             } else if(m_queue->get(&pkt, 1, &m_pktSerial) < 0) {
0110                 return -1;
0111             }
0112             if(m_queue->m_serial == m_pktSerial)
0113                 break;
0114             av_packet_free(&pkt);
0115         }
0116 
0117         if(pkt->data == FFPlayer::flushPkt()) {
0118             avcodec_flush_buffers(m_avCtx);
0119             m_finished = 0;
0120             m_nextPts = m_startPts;
0121             m_nextPtsTb = m_startPtsTb;
0122         } else if(m_avCtx->codec_type == AVMEDIA_TYPE_SUBTITLE) {
0123             int gotFrame = 0;
0124             ret = avcodec_decode_subtitle2(m_avCtx, sub, &gotFrame, pkt);
0125             if(ret < 0) {
0126                 ret = AVERROR(EAGAIN);
0127             } else if(gotFrame) {
0128                 ret = 0;
0129                 if(!pkt->data) {
0130                     m_pkt = pkt;
0131                     pkt = nullptr;
0132                 }
0133             } else {
0134                 ret = pkt->data ? AVERROR(EAGAIN) : AVERROR_EOF;
0135             }
0136         } else if(avcodec_send_packet(m_avCtx, pkt) == AVERROR(EAGAIN)) {
0137             av_log(m_avCtx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n");
0138             m_pkt = pkt;
0139             pkt = nullptr;
0140         }
0141         av_packet_free(&pkt);
0142     }
0143 }
0144 
0145 void
0146 Decoder::destroy()
0147 {
0148     av_packet_free(&m_pkt);
0149     avcodec_free_context(&m_avCtx);
0150 }
0151 
0152 void
0153 Decoder::abort()
0154 {
0155     m_queue->abort();
0156     if(m_frameQueue)
0157         m_frameQueue->signal();
0158     requestInterruption();
0159     wait();
0160     m_queue->flush();
0161 }