Я новичок ie в FFmpeg и пытаюсь использовать FFMPEG для воспроизведения потока RTSP на Android, но он будет играть все медленнее и медленнее - PullRequest
1 голос
/ 09 апреля 2020

Я новичок ie в FFmpeg и пытаюсь использовать FFMPEG для воспроизведения потока RTSP на Android, но он будет проигрываться все медленнее и медленнее. Изображение моего плеера и источника видео увеличится с разницей во времени. Видео не синхронизировано. Я тяну по локальной сети。 Чем дольше она воспроизводится, тем больше будет изображение источника видео. Более того, он не может автоматически вернуться к изображению в реальном времени, как аппаратное декодирование MediaCode. Декодированное изображение находится в замедленном режиме, и через некоторое время оно замерзает. Как я могу оптимизировать это。 это мой код

        avformat_network_init();
        AVFormatContext *pFormatCtx = avformat_alloc_context();
        AVCodecContext *pCodecCtx = avcodec_alloc_context3(nullptr);
        AVDictionary *dic = nullptr;
        int res;
        res = av_dict_set(&dic, "buffer_size", "102400", 0);
        res = av_dict_set(&dic, "rtsp_transport", "tcp", 0);
        res = av_dict_set(&dic, "stimeout", "5000000", 0);
        if (avformat_open_input(&pFormatCtx, input_str, nullptr, &dic) != 0) {
            removePlayThree(pFormatCtx, pCodecCtx);
            return;
        }
        if (avformat_find_stream_info(pFormatCtx, nullptr) < 0) {
            removePlayThree(pFormatCtx, pCodecCtx);
            return;;
        }
        if (isPlayThree == 0) {
            removePlayThree(pFormatCtx, pCodecCtx);
            return;
        }
        int videoindex = -1;
        for (int i = 0; i < pFormatCtx->nb_streams; i++) {
            if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
                videoindex < 0) {
                videoindex = i;
            }
        }
        if (videoindex == -1) {
            removePlayThree(pFormatCtx, pCodecCtx);
            return;;
        }
        if (pCodecCtx == nullptr) {
            removePlayThree(pFormatCtx, pCodecCtx);
            return;;
        }
        avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoindex]->codecpar);
        AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
        if (pCodec == nullptr) {
            removePlayThree(pFormatCtx, pCodecCtx);
            return;;
        }
        if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0) {
            removePlayThree(pFormatCtx, pCodecCtx);
            return;;
        }

        ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
        ANativeWindow_Buffer windowBuffer{};
        if (nullptr == nativeWindow) {
            return;
        }
        int width = pCodecCtx->width;
        int height = pCodecCtx->height;

        AVFrame *vFrame = av_frame_alloc();
        auto *vPacket = (AVPacket *) av_malloc(sizeof(AVPacket));
        AVFrame *pFrameRGBA = av_frame_alloc();

        if (0 >
            ANativeWindow_setBuffersGeometry(nativeWindow, width, height,
                                             WINDOW_FORMAT_RGBA_8888)) {
            ANativeWindow_release(nativeWindow);
            removePlayThree(pFormatCtx, pCodecCtx);
            if (pFrameRGBA != nullptr)
                av_free(pFrameRGBA);
            return;
        }
        pCodecCtx->thread_count = 2;


        pCodecCtx->flags = AV_CODEC_FLAG_GLOBAL_HEADER | AV_CODEC_FLAG_LOW_DELAY;
        struct SwsContext *img_convert_ctx = sws_getContext(width, height, pCodecCtx->pix_fmt,
                                                            width, height, AV_PIX_FMT_RGBA,
                                                            SWS_BICUBIC,
                                                            nullptr, nullptr, nullptr);;

        int i = 0;
        ANativeWindow_lock(nativeWindow, &windowBuffer, nullptr);
        while (av_read_frame(pFormatCtx, vPacket) >= 0) {


            if (vPacket->stream_index == videoindex) {


                avcodec_send_packet(pCodecCtx, vPacket);
                avcodec_receive_frame(pCodecCtx, vFrame);
                ANativeWindow_lock(nativeWindow, &windowBuffer, nullptr);
                av_image_fill_arrays(pFrameRGBA->data, pFrameRGBA->linesize,
                                     (const uint8_t *) windowBuffer.bits, AV_PIX_FMT_RGBA,
                                     width, height, 1);
                int re = libyuv::I420ToARGB(vFrame->data[0], vFrame->linesize[0],
                                            vFrame->data[2], vFrame->linesize[2],
                                            vFrame->data[1], vFrame->linesize[1],
                                            pFrameRGBA->data[0], pFrameRGBA->linesize[0],
                                            pCodecCtx->width, pCodecCtx->height);

                if (re == -1) {
                    avcodec_flush_buffers(pCodecCtx);

                } else {
                    ANativeWindow_unlockAndPost(nativeWindow);
                }
            }
            av_packet_unref(vPacket);

        }
        if (vPacket != nullptr)
            av_free(vPacket);
        if (pCodecCtx != nullptr)
            avcodec_close(pCodecCtx);
        if (pFrameRGBA != nullptr)
            av_free(pFrameRGBA);
        if (pFormatCtx != nullptr)
            avformat_close_input(&pFormatCtx);
        if (img_convert_ctx != nullptr)
            sws_freeContext(img_convert_ctx);
...