以下是使用C++和FFmpeg库实现从MP4文件中截取指定时刻的一帧的示例代码:
#include <iostream>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}
int main() {
av_register_all();
AVFormatContext* formatContext = nullptr;
if (avformat_open_input(&formatContext, "input.mp4", nullptr, nullptr) != 0) {
std::cerr << "Could not open input file" << std::endl;
return -1;
}
if (avformat_find_stream_info(formatContext, nullptr) < 0) {
std::cerr << "Failed to retrieve input stream information" << std::endl;
return -1;
}
int videoStreamIndex = -1;
for (unsigned int i = 0; i < formatContext->nb_streams; ++i) {
if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
break;
}
}
if (videoStreamIndex == -1) {
std::cerr << "Could not find video stream in the input file" << std::endl;
return -1;
}
AVCodecParameters* codecParameters = formatContext->streams[videoStreamIndex]->codecpar;
AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id);
if (!codec) {
std::cerr << "Unsupported codec" << std::endl;
return -1;
}
AVCodecContext* codecContext = avcodec_alloc_context3(codec);
if (!codecContext) {
std::cerr << "Failed to allocate codec context" << std::endl;
return -1;
}
if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) {
std::cerr << "Failed to copy codec parameters to codec context" << std::endl;
return -1;
}
if (avcodec_open2(codecContext, codec, nullptr) < 0) {
std::cerr << "Failed to open codec" << std::endl;
return -1;
}
AVPacket packet;
av_init_packet(&packet);
while (av_read_frame(formatContext, &packet) >= 0) {
if (packet.stream_index == videoStreamIndex) {
AVFrame* frame = av_frame_alloc();
int response = avcodec_send_packet(codecContext, &packet);
if (response < 0 && response != AVERROR(EAGAIN) && response != AVERROR_EOF)
break;
response = avcodec_receive_frame(codecContext, frame);
if (response == 0) {
// 截取指定时刻的一帧
int64_t timestampToSeek = static_cast<int64_t>(10 * AV_TIME_BASE); // 单位:微秒,此处表示第10秒
if (frame->pts >= timestampToSeek || frame->pkt_pts >= timestampToSeek)
break; // 已经截取到指定时刻的一帧
av_frame_unref(frame);
}
av_frame_free(&frame);
}
av_packet_unref(&packet);
}
avformat_close_input(&formatContext);
avformat_free_context(formatContext);
return 0;
}
请注意,这只是一个简单示例代码,仅提供了基本的流程和关键步骤,你可能需要根据实际情况进行更详细的错误处理和资源释放。同时,请确保已经将FFmpeg库正确地链接到你的项目中,并设置正确的包含路径。
内容由零声教学AI助手提供,问题来源于学员提问