【发布时间】:2016-09-06 10:41:13
【问题描述】:
我们正在开发一个使用 FFMPEG 库的项目,用于在 Android 平台上提取视频帧。
在 Windows 上,我们观察到:
- 使用 CLI,ffmpeg 能够使用命令
ffmpeg -i input.flv -vf fps=1 out%d.png以 30 fps 的速度提取帧。 - 使用 Xuggler,我们能够以 30 fps 的速度提取帧。
- 直接在代码中使用 FFMPEG API,我们以 30 fps 的速度获取帧。
但是当我们直接在 Android (See Hardware Details) 上使用 FFMPEG API 时,我们会得到以下结果:
- 720p 视频 (1280 x 720) - 16 fps(约 60 毫秒/帧)
- 1080p 视频 (1920 x 1080) - 7 fps(约 140 毫秒/帧)
我们尚未在 Android 上测试 Xuggler/CLI。
理想情况下,我们应该能够以恒定的时间(大约 30 毫秒/帧)获取数据。
我们如何在 Android 上获得 30 fps?
Android 上使用的代码:
if (avformat_open_input(&pFormatCtx, pcVideoFile, NULL, NULL)) {
iError = -1; //Couldn't open file
}
if (!iError) {
//Retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
iError = -2; //Couldn't find stream information
}
//Find the first video stream
if (!iError) {
for (i = 0; i < pFormatCtx->nb_streams; i++) {
if (AVMEDIA_TYPE_VIDEO
== pFormatCtx->streams[i]->codec->codec_type) {
iFramesInVideo = pFormatCtx->streams[i]->nb_index_entries;
duration = pFormatCtx->streams[i]->duration;
begin = pFormatCtx->streams[i]->start_time;
time_base = (pFormatCtx->streams[i]->time_base.num * 1.0f)
/ pFormatCtx->streams[i]->time_base.den;
pCodecCtx = avcodec_alloc_context3(NULL);
if (!pCodecCtx) {
iError = -6;
break;
}
AVCodecParameters params = { 0 };
iReturn = avcodec_parameters_from_context(¶ms,
pFormatCtx->streams[i]->codec);
if (iReturn < 0) {
iError = -7;
break;
}
iReturn = avcodec_parameters_to_context(pCodecCtx, ¶ms);
if (iReturn < 0) {
iError = -7;
break;
}
//pCodecCtx = pFormatCtx->streams[i]->codec;
iVideoStreamIndex = i;
break;
}
}
}
if (!iError) {
if (iVideoStreamIndex == -1) {
iError = -3; // Didn't find a video stream
}
}
if (!iError) {
// Find the decoder for the video stream
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
iError = -4;
}
}
if (!iError) {
// Open codec
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
iError = -5;
}
if (!iError) {
iNumBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height, 1);
// initialize SWS context for software scaling
sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_RGB24,
SWS_BILINEAR,
NULL,
NULL,
NULL);
if (!sws_ctx) {
iError = -7;
}
}
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
delta_us = (end.tv_sec - start.tv_sec) * 1000000
+ (end.tv_nsec - start.tv_nsec) / 1000;
start = end;
//LOGI("Starting_Frame_Extraction: %lld", delta_us);
if (!iError) {
while (av_read_frame(pFormatCtx, &packet) == 0) {
// Is this a packet from the video stream?
if (packet.stream_index == iVideoStreamIndex) {
pFrame = av_frame_alloc();
if (NULL == pFrame) {
iError = -8;
break;
}
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &iFrameFinished,
&packet);
if (iFrameFinished) {
//OUR CODE
}
av_frame_free(&pFrame);
pFrame = NULL;
}
av_packet_unref(&packet);
}
}
【问题讨论】:
-
“30 fps”是什么意思?如果给出你测试过的
ffmpeg命令行,会更好理解。 -
30 fps 表示....假设 10 秒视频中有 300 帧,那么命令行能够在 10 秒内提取这 300 帧并将其保存在磁盘上。使用的命令行:
ffmpeg -i <input_path> -vf fps=30 out%d.png -
投反对票有什么好的理由吗?
-
请看gitter.im/mobile-ffmpeg/Lobby?at=5c5bb384f04ef00644f1bb4e 下面几行,他们提到了加速进程的选项,例如... -preset ultrafast, -threads 10, -tune zerolatency, -x264-params切片线程=1
标签: android performance video ffmpeg frame-rate