Ticket #6753: avfd_packet_queues_v1.diff

File avfd_packet_queues_v1.diff, 14.7 KB (added by janne, 3 years ago)

implements packet queues for avformatdecoder

  • libs/libmythtv/avformatdecoder.cpp

     
    182182typedef MythDeque<AVFrame*> avframe_q; 
    183183 
    184184/** 
     185 * Queues for AVPackets 
     186 */ 
     187 
     188struct CountedPacket 
     189{ 
     190        uint64_t    count; 
     191        AVPacket   *packet; 
     192}; 
     193 
     194class AVPacketQueues 
     195{ 
     196    public: 
     197        AVPacketQueues() 
     198            : m_count(0) { ; } 
     199        ~AVPacketQueues(); 
     200 
     201        void Flush(void); 
     202        bool IsFilled(void); 
     203        void PrintQueueStatus(void); 
     204        CountedPacket *TakeFirstPacket(enum CodecType type); 
     205        AVPacket *NextPacket(void); 
     206        void PushBack(AVPacket *pkt, enum CodecType); 
     207 
     208    private: 
     209        QList<CountedPacket*> m_videoPacketQueue; 
     210        QList<CountedPacket*> m_audioPacketQueue; 
     211        QList<CountedPacket*> m_subtitlePacketQueue; 
     212        QList<CountedPacket*> m_dataPacketQueue; 
     213        uint64_t              m_count; 
     214}; 
     215 
     216AVPacketQueues::~AVPacketQueues() 
     217{ 
     218    Flush(); 
     219} 
     220 
     221static void flush_packet_queue(QList<CountedPacket*> pq) 
     222{ 
     223    while (!pq.isEmpty()) 
     224    { 
     225        CountedPacket *pkt = pq.takeFirst(); 
     226        av_free_packet(pkt->packet); 
     227        av_free(pkt->packet); 
     228        delete pkt; 
     229    } 
     230} 
     231 
     232void AVPacketQueues::Flush(void) 
     233{ 
     234    flush_packet_queue(m_videoPacketQueue); 
     235    flush_packet_queue(m_audioPacketQueue); 
     236    flush_packet_queue(m_subtitlePacketQueue); 
     237    flush_packet_queue(m_dataPacketQueue); 
     238} 
     239 
     240bool AVPacketQueues::IsFilled(void) 
     241{ 
     242    bool filled = 
     243         m_videoPacketQueue.count()    && 
     244         m_audioPacketQueue.count()    && 
     245         m_subtitlePacketQueue.count() && 
     246         m_dataPacketQueue.count(); 
     247 
     248    filled |= m_videoPacketQueue.count() > 100; 
     249    filled |= m_audioPacketQueue.count() > 250; 
     250 
     251    return filled; 
     252} 
     253 
     254void AVPacketQueues::PrintQueueStatus(void) 
     255{ 
     256    VERBOSE(VB_IMPORTANT, QString("packet queue status %1, v:%2, a:%3, s:%4, d:%5") 
     257            .arg(IsFilled()) 
     258            .arg(m_videoPacketQueue.count()) 
     259            .arg(m_audioPacketQueue.count()) 
     260            .arg(m_subtitlePacketQueue.count()) 
     261            .arg(m_dataPacketQueue.count())); 
     262} 
     263 
     264CountedPacket *AVPacketQueues::TakeFirstPacket(enum CodecType type) 
     265{ 
     266    CountedPacket *pkt = NULL; 
     267 
     268    switch (type) 
     269    { 
     270        case CODEC_TYPE_VIDEO: 
     271            if (!m_videoPacketQueue.isEmpty()) 
     272                pkt = m_videoPacketQueue.takeFirst(); 
     273            break; 
     274        case CODEC_TYPE_AUDIO: 
     275            if (!m_audioPacketQueue.isEmpty()) 
     276                pkt = m_audioPacketQueue.takeFirst(); 
     277            break; 
     278        case CODEC_TYPE_SUBTITLE: 
     279            if (!m_subtitlePacketQueue.isEmpty()) 
     280                pkt = m_subtitlePacketQueue.takeFirst(); 
     281            break; 
     282        case CODEC_TYPE_DATA: 
     283            if (!m_dataPacketQueue.isEmpty()) 
     284                pkt = m_dataPacketQueue.takeFirst(); 
     285            break; 
     286        default: 
     287            return NULL; 
     288    } 
     289 
     290    return pkt; 
     291} 
     292 
     293static void find_min_packet(CountedPacket* pkt, int64_t &min_pts, uint64_t &min_pts_count, 
     294                            enum CodecType &nextq_pts, 
     295                            uint64_t &min_count, enum CodecType &nextq_count, 
     296                            enum CodecType type) 
     297{ 
     298    int64_t pts = pkt->packet->dts; 
     299 
     300    if (pts != (int64_t)AV_NOPTS_VALUE && (min_pts == (int64_t)AV_NOPTS_VALUE || pts < min_pts)) 
     301    { 
     302        min_pts       = pts; 
     303        min_pts_count = pkt->count; 
     304        nextq_pts     = type; 
     305    } 
     306    if (pts == (int64_t)AV_NOPTS_VALUE && pkt->count < min_count) 
     307    { 
     308        min_count   = pkt->count; 
     309        nextq_count = type; 
     310    } 
     311} 
     312 
     313AVPacket *AVPacketQueues::NextPacket(void) 
     314{ 
     315    CountedPacket *pkt       = NULL; 
     316    int64_t        min_pts   = (int64_t)AV_NOPTS_VALUE; 
     317    uint64_t       min_count = ~0ULL; 
     318 
     319    uint64_t       min_pts_count; 
     320    enum CodecType nextq_pts, nextq_count; 
     321 
     322    if (!m_videoPacketQueue.isEmpty()) 
     323    { 
     324        pkt = m_videoPacketQueue.first(); 
     325        find_min_packet(pkt, min_pts, min_pts_count, nextq_pts, min_count, 
     326                        nextq_count, CODEC_TYPE_VIDEO); 
     327    } 
     328    if (!m_audioPacketQueue.isEmpty()) 
     329    { 
     330        pkt = m_audioPacketQueue.first(); 
     331        find_min_packet(pkt, min_pts, min_pts_count, nextq_pts, min_count, 
     332                        nextq_count, CODEC_TYPE_AUDIO); 
     333    } 
     334    if (!m_subtitlePacketQueue.isEmpty()) 
     335    { 
     336        pkt = m_subtitlePacketQueue.first(); 
     337        find_min_packet(pkt, min_pts, min_pts_count, nextq_pts, min_count, 
     338                        nextq_count, CODEC_TYPE_SUBTITLE); 
     339    } 
     340    if (!m_dataPacketQueue.isEmpty()) 
     341    { 
     342        pkt = m_dataPacketQueue.first(); 
     343        find_min_packet(pkt, min_pts, min_pts_count, nextq_pts, min_count, 
     344                        nextq_count, CODEC_TYPE_DATA); 
     345    } 
     346 
     347    if (min_pts != (int64_t)AV_NOPTS_VALUE && min_pts_count <= min_count) 
     348    { 
     349//         VERBOSE(VB_IMPORTANT, QString("Taking one %1 packet count %2 pts %3 - other_cnt %4") 
     350//                 .arg(nextq_pts).arg(min_pts_count).arg(min_pts).arg(min_count)); 
     351        pkt = TakeFirstPacket(nextq_pts); 
     352    } 
     353    else if (min_count < ~0ULL) 
     354    { 
     355//         VERBOSE(VB_IMPORTANT, QString("Taking one %1 packet count %2 - pts %3 other_cnt %4") 
     356//                 .arg(nextq_count).arg(min_count).arg(min_pts).arg(min_pts_count)); 
     357        pkt = TakeFirstPacket(nextq_count); 
     358    } 
     359    else 
     360    { 
     361        VERBOSE(VB_IMPORTANT, "no packet found"); 
     362        return NULL; 
     363    } 
     364 
     365    AVPacket *packet = pkt->packet; 
     366    delete pkt; 
     367 
     368    return packet; 
     369} 
     370 
     371void AVPacketQueues::PushBack(AVPacket *pkt, enum CodecType type) 
     372{ 
     373    av_dup_packet(pkt); 
     374 
     375//     VERBOSE(VB_IMPORTANT, QString("Adding packet %1 with type %2") 
     376//             .arg(m_count).arg((int)type)); 
     377 
     378    CountedPacket *cpkt = new CountedPacket(); 
     379    cpkt->count  = m_count++; 
     380    cpkt->packet = pkt; 
     381 
     382    switch (type) 
     383    { 
     384        case CODEC_TYPE_VIDEO: 
     385            m_videoPacketQueue.push_back(cpkt); 
     386            break; 
     387        case CODEC_TYPE_AUDIO: 
     388            m_audioPacketQueue.push_back(cpkt); 
     389            break; 
     390        case CODEC_TYPE_SUBTITLE: 
     391            m_subtitlePacketQueue.push_back(cpkt); 
     392            break; 
     393        case CODEC_TYPE_DATA: 
     394            m_dataPacketQueue.push_back(cpkt); 
     395            break; 
     396        default: 
     397            av_free_packet(pkt); 
     398            av_free(pkt); 
     399            return; 
     400    } 
     401} 
     402 
     403/** 
    185404 * Management of libmpeg2 decoding 
    186405 */ 
    187406class AvFormatDecoderPrivate 
     
    439658      m_h264_parser(new H264Parser()), 
    440659      ic(NULL), 
    441660      frame_decoded(0),             decoded_video_frame(NULL), 
    442       avfRingBuffer(NULL), 
     661      avfRingBuffer(NULL),          m_packet_queue(new AVPacketQueues()), 
    443662      directrendering(false),       drawband(false), 
    444663      gopset(false),                seen_gop(false), 
    445664      seq_count(0),                 firstgoppos(0), 
     
    494713 
    495714AvFormatDecoder::~AvFormatDecoder() 
    496715{ 
    497     while (!storedPackets.isEmpty()) 
    498     { 
    499         AVPacket *pkt = storedPackets.takeFirst(); 
    500         av_free_packet(pkt); 
    501         delete pkt; 
    502     } 
     716    delete m_packet_queue; 
    503717 
    504718    CloseContext(); 
    505719    delete ccd608; 
     
    727941    if (doflush) 
    728942    { 
    729943        // Free up the stored up packets 
    730         while (!storedPackets.isEmpty()) 
    731         { 
    732             AVPacket *pkt = storedPackets.takeFirst(); 
    733             av_free_packet(pkt); 
    734             delete pkt; 
    735         } 
     944        m_packet_queue->Flush(); 
    736945 
    737946        prevgoppos = 0; 
    738947        gopset = false; 
     
    31933402    } 
    31943403} 
    31953404 
     3405 
     3406AVPacket *AvFormatDecoder::GetNextPacket() 
     3407{ 
     3408    if (!ic) 
     3409        return NULL; 
     3410 
     3411//     m_packet_queue->PrintQueueStatus(); 
     3412 
     3413    while (!m_packet_queue->IsFilled()) 
     3414    { 
     3415        AVPacket *pkt = (AVPacket*)av_mallocz(sizeof(AVPacket)); 
     3416        av_init_packet(pkt); 
     3417 
     3418        if (av_read_frame(ic, pkt) < 0) 
     3419        { 
     3420                av_free_packet(pkt); 
     3421                av_freep(&pkt); 
     3422                break; 
     3423        } 
     3424         
     3425        if (pkt->stream_index > (int) ic->nb_streams) 
     3426        { 
     3427            VERBOSE(VB_IMPORTANT, LOC_ERR + "Bad stream"); 
     3428            av_free_packet(pkt); 
     3429            av_freep(&pkt); 
     3430            continue; 
     3431        } 
     3432 
     3433        AVStream *curstream = ic->streams[pkt->stream_index]; 
     3434 
     3435        switch (curstream->codec->codec_type) 
     3436        { 
     3437            case CODEC_TYPE_VIDEO: 
     3438            case CODEC_TYPE_AUDIO: 
     3439            case CODEC_TYPE_SUBTITLE: 
     3440                    m_packet_queue->PushBack(pkt, curstream->codec->codec_type); 
     3441                    break; 
     3442            case CODEC_TYPE_DATA: 
     3443                if (curstream->codec->codec_id == CODEC_ID_MPEG2VBI || 
     3444                    curstream->codec->codec_id == CODEC_ID_DVB_VBI  || 
     3445                    curstream->codec->codec_id == CODEC_ID_DSMCC_B) 
     3446                { 
     3447                    m_packet_queue->PushBack(pkt, CODEC_TYPE_DATA); 
     3448                    break; 
     3449                } 
     3450            default: 
     3451                av_free_packet(pkt); 
     3452                av_freep(&pkt); 
     3453        } 
     3454    } 
     3455 
     3456//     m_packet_queue->PrintQueueStatus(); 
     3457 
     3458    return m_packet_queue->NextPacket(); 
     3459} 
     3460 
     3461 
    31963462// documented in decoderbase.h 
    31973463bool AvFormatDecoder::GetFrame(int onlyvideo) 
    31983464{ 
     
    32093475    decoded_video_frame = NULL; 
    32103476 
    32113477    bool allowedquit = false; 
    3212     bool storevideoframes = false; 
    32133478 
    32143479    avcodeclock.lock(); 
    32153480    AutoSelectTracks(); 
     
    32333498        allowedquit = (onlyvideo < 0) && (ofill > othresh); 
    32343499    } 
    32353500 
    3236     while (!allowedquit) 
     3501    while (!allowedquit && !frame_decoded) 
    32373502    { 
    32383503        if ((onlyvideo == 0) && 
    32393504            ((currentTrack[kTrackTypeAudio] < 0) || 
     
    32583523            selectedVideoIndex = 0; 
    32593524            if (dvdTitleChanged) 
    32603525            { 
    3261                 if ((storedPackets.count() > 10 && !decodeStillFrame) || 
    3262                     decodeStillFrame) 
     3526                if (decodeStillFrame) 
    32633527                { 
    3264                     storevideoframes = false; 
    32653528                    dvdTitleChanged = false; 
    32663529                    ScanStreams(true); 
    32673530                } 
    3268                 else 
    3269                     storevideoframes = true; 
    32703531            } 
    32713532            else 
    32723533            { 
    3273                 storevideoframes = false; 
    3274  
    3275                 if (storedPackets.count() < 2 && !decodeStillFrame) 
    3276                     storevideoframes = true; 
    3277  
    3278                 VERBOSE(VB_PLAYBACK+VB_EXTRA, QString("DVD Playback Debugging " 
    3279                     "inDVDMenu %1 storedPacketcount %2 dvdstill %3") 
    3280                     .arg(inDVDMenu).arg(storedPackets.count()).arg(inDVDStill)); 
    3281  
    3282                 if (inDVDMenu && storedPackets.count() > 0) 
     3534                if (inDVDMenu) 
    32833535                    ringBuffer->DVD()->SetRunSeekCellStart(false); 
    3284                 else if (storedPackets.count() == 0) 
    3285                     ringBuffer->DVD()->RunSeekCellStart(); 
    32863536            } 
    32873537            if (GetNVP()->AtNormalSpeed() && 
    32883538                ((cellChanged) || (lastdvdtitle != dvdtitle))) 
     
    33193569            } 
    33203570        } 
    33213571 
    3322         if (gotvideo) 
    3323         { 
    3324             if (lowbuffers && onlyvideo == 0 && 
    3325                 storedPackets.count() < max_video_queue_size && 
    3326                 lastapts < lastvpts + 100 && 
    3327                 !ringBuffer->InDVDMenuOrStillFrame()) 
    3328             { 
    3329                 storevideoframes = true; 
    3330             } 
    3331             else if (onlyvideo >= 0) 
    3332             { 
    3333                 if (storedPackets.count() >= max_video_queue_size) 
    3334                     VERBOSE(VB_IMPORTANT, 
    3335                             QString("Audio %1 ms behind video but already %2 " 
    3336                                "video frames queued. AV-Sync might be broken.") 
    3337                             .arg(lastvpts-lastapts).arg(storedPackets.count())); 
    3338                 allowedquit = true; 
    3339                 continue; 
    3340             } 
    3341         } 
     3572        pkt = GetNextPacket(); 
    33423573 
    3343         if (!storevideoframes && storedPackets.count() > 0) 
     3574        if (!pkt) 
    33443575        { 
    3345             if (pkt) 
    3346             { 
    3347                 av_free_packet(pkt); 
    3348                 delete pkt; 
    3349             } 
    3350             pkt = storedPackets.takeFirst(); 
    3351         } 
    3352         else 
    3353         { 
    3354             if (!pkt) 
    3355             { 
    3356                 pkt = new AVPacket; 
    3357                 bzero(pkt, sizeof(AVPacket)); 
    3358                 av_init_packet(pkt); 
    3359             } 
    3360  
    3361             if (!ic || (av_read_frame(ic, pkt) < 0)) 
    3362             { 
     3576            VERBOSE(VB_IMPORTANT, LOC_ERR + "no packet, stream ended?"); 
    33633577                ateof = true; 
    33643578                GetNVP()->SetEof(); 
    33653579                delete pkt; 
     
    33793593 
    33803594            if (pkt->pos > readAdjust) 
    33813595                pkt->pos -= readAdjust; 
    3382         } 
    33833596 
    33843597        if (pkt->stream_index > (int) ic->nb_streams) 
    33853598        { 
     
    34593672            } 
    34603673        } 
    34613674 
    3462         if (storevideoframes && 
    3463             curstream->codec->codec_type == CODEC_TYPE_VIDEO) 
    3464         { 
    3465             av_dup_packet(pkt); 
    3466             storedPackets.append(pkt); 
    3467             pkt = NULL; 
    3468             continue; 
    3469         } 
    3470  
    34713675        if (len > 0 && curstream->codec->codec_type == CODEC_TYPE_VIDEO && 
    34723676            pkt->stream_index == selectedVideoIndex) 
    34733677        { 
     
    40424246 
    40434247                    if (gotSubtitles) 
    40444248                    { 
     4249                        VERBOSE(VB_PLAYBACK|VB_EXTRA, QString("Got Subtitle. pts = %1, start %2 - end = %3") 
     4250                                .arg(pts).arg(subtitle.start_display_time).arg(subtitle.end_display_time)); 
    40454251                        subtitle.start_display_time += pts; 
    40464252                        subtitle.end_display_time += pts; 
    40474253                        GetNVP()->AddAVSubtitle(subtitle); 
  • libs/libmythtv/avformatdecoder.h

     
    2525class InteractiveTV; 
    2626class ProgramInfo; 
    2727class MythSqlDatabase; 
     28class AVPacketQueues; 
    2829 
    2930extern "C" void HandleStreamChange(void*); 
    3031 
     
    170171    friend int64_t seek_avf(URLContext *h, int64_t offset, int whence); 
    171172    friend int close_avf(URLContext *h); 
    172173 
     174    AVPacket *GetNextPacket(); 
     175 
    173176    void DecodeDTVCC(const uint8_t *buf); 
    174177    void InitByteContext(void); 
    175178    void InitVideoCodec(AVStream *stream, AVCodecContext *enc, 
     
    215218    VideoFrame *decoded_video_frame; 
    216219    AVFRingBuffer *avfRingBuffer; 
    217220 
     221    AVPacketQueues  *m_packet_queue; 
     222 
    218223    bool directrendering; 
    219224    bool drawband; 
    220225 
     
    225230    bool seen_gop; 
    226231    int seq_count; ///< A counter used to determine if we need to force a call to HandleGopStart 
    227232 
    228     QList<AVPacket*> storedPackets; 
    229  
    230233    int firstgoppos; 
    231234    int prevgoppos; 
    232235