Ticket #6753: avfd_packet_queues_v1.diff

File avfd_packet_queues_v1.diff, 14.7 KB (added by Janne Grunau, 15 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