Ticket #6753: avfd_packet_queues_v1.diff
File avfd_packet_queues_v1.diff, 14.7 KB (added by , 15 years ago) |
---|
-
libs/libmythtv/avformatdecoder.cpp
182 182 typedef MythDeque<AVFrame*> avframe_q; 183 183 184 184 /** 185 * Queues for AVPackets 186 */ 187 188 struct CountedPacket 189 { 190 uint64_t count; 191 AVPacket *packet; 192 }; 193 194 class 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 216 AVPacketQueues::~AVPacketQueues() 217 { 218 Flush(); 219 } 220 221 static 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 232 void 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 240 bool 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 254 void 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 264 CountedPacket *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 293 static 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 313 AVPacket *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 371 void 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 /** 185 404 * Management of libmpeg2 decoding 186 405 */ 187 406 class AvFormatDecoderPrivate … … 439 658 m_h264_parser(new H264Parser()), 440 659 ic(NULL), 441 660 frame_decoded(0), decoded_video_frame(NULL), 442 avfRingBuffer(NULL), 661 avfRingBuffer(NULL), m_packet_queue(new AVPacketQueues()), 443 662 directrendering(false), drawband(false), 444 663 gopset(false), seen_gop(false), 445 664 seq_count(0), firstgoppos(0), … … 494 713 495 714 AvFormatDecoder::~AvFormatDecoder() 496 715 { 497 while (!storedPackets.isEmpty()) 498 { 499 AVPacket *pkt = storedPackets.takeFirst(); 500 av_free_packet(pkt); 501 delete pkt; 502 } 716 delete m_packet_queue; 503 717 504 718 CloseContext(); 505 719 delete ccd608; … … 727 941 if (doflush) 728 942 { 729 943 // 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(); 736 945 737 946 prevgoppos = 0; 738 947 gopset = false; … … 3193 3402 } 3194 3403 } 3195 3404 3405 3406 AVPacket *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 3196 3462 // documented in decoderbase.h 3197 3463 bool AvFormatDecoder::GetFrame(int onlyvideo) 3198 3464 { … … 3209 3475 decoded_video_frame = NULL; 3210 3476 3211 3477 bool allowedquit = false; 3212 bool storevideoframes = false;3213 3478 3214 3479 avcodeclock.lock(); 3215 3480 AutoSelectTracks(); … … 3233 3498 allowedquit = (onlyvideo < 0) && (ofill > othresh); 3234 3499 } 3235 3500 3236 while (!allowedquit )3501 while (!allowedquit && !frame_decoded) 3237 3502 { 3238 3503 if ((onlyvideo == 0) && 3239 3504 ((currentTrack[kTrackTypeAudio] < 0) || … … 3258 3523 selectedVideoIndex = 0; 3259 3524 if (dvdTitleChanged) 3260 3525 { 3261 if ((storedPackets.count() > 10 && !decodeStillFrame) || 3262 decodeStillFrame) 3526 if (decodeStillFrame) 3263 3527 { 3264 storevideoframes = false;3265 3528 dvdTitleChanged = false; 3266 3529 ScanStreams(true); 3267 3530 } 3268 else3269 storevideoframes = true;3270 3531 } 3271 3532 else 3272 3533 { 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) 3283 3535 ringBuffer->DVD()->SetRunSeekCellStart(false); 3284 else if (storedPackets.count() == 0)3285 ringBuffer->DVD()->RunSeekCellStart();3286 3536 } 3287 3537 if (GetNVP()->AtNormalSpeed() && 3288 3538 ((cellChanged) || (lastdvdtitle != dvdtitle))) … … 3319 3569 } 3320 3570 } 3321 3571 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(); 3342 3573 3343 if (! storevideoframes && storedPackets.count() > 0)3574 if (!pkt) 3344 3575 { 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?"); 3363 3577 ateof = true; 3364 3578 GetNVP()->SetEof(); 3365 3579 delete pkt; … … 3379 3593 3380 3594 if (pkt->pos > readAdjust) 3381 3595 pkt->pos -= readAdjust; 3382 }3383 3596 3384 3597 if (pkt->stream_index > (int) ic->nb_streams) 3385 3598 { … … 3459 3672 } 3460 3673 } 3461 3674 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 3471 3675 if (len > 0 && curstream->codec->codec_type == CODEC_TYPE_VIDEO && 3472 3676 pkt->stream_index == selectedVideoIndex) 3473 3677 { … … 4042 4246 4043 4247 if (gotSubtitles) 4044 4248 { 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)); 4045 4251 subtitle.start_display_time += pts; 4046 4252 subtitle.end_display_time += pts; 4047 4253 GetNVP()->AddAVSubtitle(subtitle); -
libs/libmythtv/avformatdecoder.h
25 25 class InteractiveTV; 26 26 class ProgramInfo; 27 27 class MythSqlDatabase; 28 class AVPacketQueues; 28 29 29 30 extern "C" void HandleStreamChange(void*); 30 31 … … 170 171 friend int64_t seek_avf(URLContext *h, int64_t offset, int whence); 171 172 friend int close_avf(URLContext *h); 172 173 174 AVPacket *GetNextPacket(); 175 173 176 void DecodeDTVCC(const uint8_t *buf); 174 177 void InitByteContext(void); 175 178 void InitVideoCodec(AVStream *stream, AVCodecContext *enc, … … 215 218 VideoFrame *decoded_video_frame; 216 219 AVFRingBuffer *avfRingBuffer; 217 220 221 AVPacketQueues *m_packet_queue; 222 218 223 bool directrendering; 219 224 bool drawband; 220 225 … … 225 230 bool seen_gop; 226 231 int seq_count; ///< A counter used to determine if we need to force a call to HandleGopStart 227 232 228 QList<AVPacket*> storedPackets;229 230 233 int firstgoppos; 231 234 int prevgoppos; 232 235