FFMPEG:avcodec_send_packet / avcodec_receive_frame,解码速度太慢

时间:2017-10-08 16:57:53

标签: objective-c multithreading performance video ffmpeg

我正在编写自己的iOS视频播放器而我正面临下一个问题 - 帧的解码速度太慢。播放器以30/60 fps完美运行,但120 fps视频以慢动作播放。

经过一番研究,我确定了解码文件的主要问题。它太慢了。

现在我有3个帖子: 1)从文件中读取 2)avcodec_send_packet,avcodec_receive_frame并生成图片的原始数据3)视频显示

问题在于2个线程,包含avcodec_send_packet和avcodec_receive_frame。

我删除了#34;从AVFrame生成图片的原始数据"从2线程来测量avcodec_send_packet / avcodec_receive_frame的执行时间,并且使用这些函数的循环几乎不能产生120 fps。当我说"勉强"我的意思是在视频的第一秒将是滞后的。

这里是解码线程的日志:

2017-10-08 19:31:55.476538 VULCAM[910:85974] SEC! 106
2017-10-08 19:31:56.484544 VULCAM[910:85974] SEC! 110
2017-10-08 19:31:57.486751 VULCAM[910:85974] SEC! 119
2017-10-08 19:31:58.491270 VULCAM[910:85974] SEC! 122
2017-10-08 19:31:59.500061 VULCAM[910:85974] SEC! 119
2017-10-08 19:32:00.507599 VULCAM[910:85974] SEC! 126
2017-10-08 19:32:01.513110 VULCAM[910:85974] SEC! 126
2017-10-08 19:32:02.517102 VULCAM[910:85974] SEC! 125
2017-10-08 19:32:03.518195 VULCAM[910:85974] SEC! 121
2017-10-08 19:32:04.528745 VULCAM[910:85974] SEC! 120
2017-10-08 19:32:05.529884 VULCAM[910:85974] SEC! 122
2017-10-08 19:32:06.540589 VULCAM[910:85974] SEC! 123

我非常确定能够更有效地使用ffmpeg并缩短执行时间。这里有一些小代码片段,足以理解整个想法。

以下是启动视频解码的方法:

- (void)play:(PlayerState)state
{

    [self decodePackets_loop];
    [self decodeFrames_loop];
    [self video_refresh];
}

此处decodePackets_loop

- (void)decodePackets_loop
{
    dispatch_queue_t pktsQueue = dispatch_queue_create("decodePacketsQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(pktsQueue, ^{


        while (_state == PlayerPlayForward) {

            AVPacket packet;
            int ret = av_read_frame(_pFormatCtx, &packet);
            if (ret < 0) {

                if (ret == AVERROR_EOF) {
                    _isCached = YES;
                    break;
                }
                else {
                    NSLog(@"av_read_frame error!");
                    continue;
                }
            }

            [_picturesQueue put:&packet];
        }
        NSLog(@"DONE!");
    });
}

此处decodeFrames_loop

- (void)decodeFrames_loop
{
    dispatch_queue_t fmsQueue = dispatch_queue_create("decodeFramesQueue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(fmsQueue, ^{

        AVFrame *pFrame = NULL;
        pFrame = av_frame_alloc();
        if (pFrame == NULL) {
            NSLog(@"Couldn't init pFrame!");
            return;
        }
        double pts = 0.0;

        NSTimeInterval currTime = [NSDate timeIntervalSinceReferenceDate];
        float sec = 0.0f;
        int frames_cnt = 0;

        while (_state == PlayerPlayForward) {

            AVPacket pkt;

            if ([_picturesQueue get:&pkt]) {

                if (avcodec_send_packet(_pCodecCtx, &pkt) != 0) {
                    NSLog(@"Couldn't send packet");
                    continue;
                }

                if (avcodec_receive_frame(_pCodecCtx, pFrame) != 0) {
                    NSLog(@"Couldn't receive frame");
                    av_packet_unref(&pkt);
                    continue;
                }

                if (pkt.dts != AV_NOPTS_VALUE)
                {
                    pts = av_frame_get_best_effort_timestamp(pFrame);
                }
                else
                {
                    pts = 0.0f;
                }
                pts *= av_q2d(_activeStream->time_base);

                av_packet_unref(&pkt);

                [self synchronizeVideo:pFrame pts:pts];
                //VideoPicture *vid_pic = [self generateVideoPictureFromFrame:pFrame withPts:pts withDts:pFrame->pkt_dts];
                /*if (vid_pic) {
                    [_picturesPool addPicture:vid_pic];
                }*/
                //av_free(vid_pic.data);

                frames_cnt++;
                sec = [NSDate timeIntervalSinceReferenceDate] - currTime;
                if (sec >= 1.0f) {
                    NSLog(@"SEC! %d", frames_cnt);
                    sec = 0.0f;
                    frames_cnt = 0;
                    currTime = [NSDate timeIntervalSinceReferenceDate];
                }
            }
        }

        av_frame_free(&pFrame);
    });
}

0 个答案:

没有答案