Chinaunix首页 | 论坛 | 博客
  • 博客访问: 481691
  • 博文数量: 1958
  • 博客积分: 44693
  • 博客等级: 大将
  • 技术积分: 22125
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-29 15:19






2011-09-15 01:29:17

FFmpeg lib + UDP + Qt issuesHello, First of all, thank you to this amazing community of developers! I have received a tremendous amount of help both directly and indirectly thanks to you all. I am in need of some help regarding reading encoded video udp packets and decoding them into a Qt display. I have managed to read the video packets and display them in Qt but video playback 'stutters'. Checking the FPS of frames transmitted via the FFMpeg library to Qt, I get ~30 frames per second, so I'm led to believe that FFMpeg itself is sending me the same frames multiple times a second. Here are the steps I took: 1. Broadcast an H.264 encoded video stream via VLC to udp:/ 2. Use FFMpeg lib to decode the stream. Here is my function (apologies in advance, if there is a better way to display code, please let me know!): bool QVideoDecoder::decodeSeekFrame(int after) { bool done=false; while(!done) { // Read a frame timeoutTimer.start(); if(av_read_frame(pFormatCtx, &packet)<0) return false; // Frame read failed (e.g. end of stream) timeoutTimer.stop(); if(packet.stream_index==videoStream) { int frameFinished; avcodec_decode_video2(pCodecCtx,pFrame,&frameFinished,&packet); // Did we get a video frame? if(frameFinished) { ffmpeg::AVRational millisecondbase = {1, 1000}; int f = packet.dts; int t = ffmpeg::av_rescale_q(packet.dts,pFormatCtx->streams[videoStream]->time_base,millisecondbase); if(LastFrameOk==false) { LastFrameOk=true; LastLastFrameTime=LastFrameTime=t; LastLastFrameNumber=LastFrameNumber=f; } else { // If we decoded 2 frames in a row, the last times are okay LastLastFrameTime = LastFrameTime; LastLastFrameNumber = LastFrameNumber; LastFrameTime=t; LastFrameNumber=f; } // Is this frame the desired frame? if(after==-1 || LastFrameNumber>=after) { // Convert the image format (init the context the first time) int w = pCodecCtx->width; int h = pCodecCtx->height; img_convert_ctx = ffmpeg::sws_getCachedContext(img_convert_ctx,w, h, pCodecCtx->pix_fmt, w, h, ffmpeg::PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL); if(img_convert_ctx == NULL) { printf("Cannot initialize the conversion context!\n"); return false; } ffmpeg::sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); // Convert the frame to QImage LastFrame=QImage(w,h,QImage::Format_RGB888); for(int y=0;y<h;y++) memcpy(LastFrame.scanLine(y),pFrameRGB->data[0]+y*pFrameRGB->linesize[0],w*3); // Set the time DesiredFrameTime = ffmpeg::av_rescale_q(after,pFormatCtx->streams[videoStream]->time_base,millisecondbase); LastFrameOk=true; done = true; } } } av_free_packet(&packet); } return done; } I have a periodic timer that requests the latest frame from FFMpeg. If I set the timer to a low rate (20 FPS), I get the video played back but at a slow rate. If I set the timer to a high rate (60 FPS), I get the frames as soon as they are ready, but the video stutters. I figured that I should request the frames back as fast as possible.. Any insight on how to avoid the stuttering is appreciated. 3. Send the QImage back to Qt to be displayed -- I have tested the frames received by my Qt callback per second and can confirm that I am receiving ~ 30 FPS which leads me to believe the stuttering is caused by FFMpeg lib. 4. I also wrote an interrupting callback to be called by FFMpeg if any of the blocking functions (i.e. av_read_frame) took too long: Timer timeoutTimer; static int decode_interrupt_cb(void) { if (timeoutTimer.getElapsedTimeInMilliSec() > 1000) { qDebug() << "Video Timed Out!"; return 1; } return 0; } Although I sometimes do receive the "Video Timed Out!" call, the av_read_frame function still blocks... Any help would be greatly appreciated!

阅读(1021) | 评论(0) | 转发(1) |