Я новичок 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);