基于FFMPEG的MP4播放器,C++代码
时间: 2024-05-12 09:15:08 浏览: 86
以下是一个基于FFMPEG的简单MP4播放器的C++代码示例:
```
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
}
using namespace std;
using namespace chrono_literals;
int main(int argc, char *argv[])
{
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <filename>" << endl;
return 1;
}
// Register all codecs and formats
av_register_all();
// Open the input file
AVFormatContext *format_ctx = nullptr;
if (avformat_open_input(&format_ctx, argv[1], nullptr, nullptr) != 0) {
cerr << "Error: could not open input file." << endl;
return 1;
}
// Retrieve stream information
if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
cerr << "Error: could not find stream information." << endl;
return 1;
}
// Find the first video stream
int video_stream_index = -1;
for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
break;
}
}
if (video_stream_index == -1) {
cerr << "Error: could not find video stream." << endl;
return 1;
}
// Get a pointer to the codec context for the video stream
AVCodecParameters *codec_params = format_ctx->streams[video_stream_index]->codecpar;
AVCodec *codec = avcodec_find_decoder(codec_params->codec_id);
if (!codec) {
cerr << "Error: could not find decoder for codec." << endl;
return 1;
}
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
cerr << "Error: could not allocate codec context." << endl;
return 1;
}
if (avcodec_parameters_to_context(codec_ctx, codec_params) < 0) {
cerr << "Error: could not copy codec parameters to codec context." << endl;
return 1;
}
if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
cerr << "Error: could not open codec." << endl;
return 1;
}
// Allocate video frame and buffer
AVFrame *frame = av_frame_alloc();
if (!frame) {
cerr << "Error: could not allocate video frame." << endl;
return 1;
}
int num_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
uint8_t *buffer = (uint8_t*) av_malloc(num_bytes * sizeof(uint8_t));
av_image_fill_arrays(frame->data, frame->linesize, buffer, AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
// Allocate RGB frame
AVFrame *rgb_frame = av_frame_alloc();
if (!rgb_frame) {
cerr << "Error: could not allocate RGB frame." << endl;
return 1;
}
num_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
buffer = (uint8_t*) av_malloc(num_bytes * sizeof(uint8_t));
av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, buffer, AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
// Allocate packet
AVPacket *packet = av_packet_alloc();
if (!packet) {
cerr << "Error: could not allocate packet." << endl;
return 1;
}
// Initialize scaling context
SwsContext *sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
codec_ctx->width, codec_ctx->height, AV_PIX_FMT_RGB24,
SWS_BILINEAR, nullptr, nullptr, nullptr);
// Initialize display window
const string window_title = "MP4 Player";
const int window_width = codec_ctx->width;
const int window_height = codec_ctx->height;
cv::namedWindow(window_title, cv::WINDOW_NORMAL);
cv::resizeWindow(window_title, window_width, window_height);
// Start reading packets from the stream
int ret = 0;
while (av_read_frame(format_ctx, packet) >= 0) {
// Check if the packet is from the video stream
if (packet->stream_index == video_stream_index) {
// Decode the packet
ret = avcodec_send_packet(codec_ctx, packet);
if (ret < 0) {
cerr << "Error: could not send packet to decoder." << endl;
break;
}
while (ret >= 0) {
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0) {
cerr << "Error: could not receive frame from decoder." << endl;
goto end;
}
// Convert the frame to RGB format
sws_scale(sws_ctx, frame->data, frame->linesize, 0, codec_ctx->height, rgb_frame->data, rgb_frame->linesize);
// Display the frame
cv::Mat frame_mat = cv::Mat(codec_ctx->height, codec_ctx->width, CV_8UC3, rgb_frame->data[0]);
cv::imshow(window_title, frame_mat);
cv::waitKey(1);
}
}
// Free the packet
av_packet_unref(packet);
}
end:
// Free resources
avformat_close_input(&format_ctx);
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
av_frame_free(&rgb_frame);
av_packet_free(&packet);
sws_freeContext(sws_ctx);
return 0;
}
```
请注意,这只是一个简单的示例代码,没有包含错误处理和其他优化。如果您想要开发一个稳健的MP4播放器,需要更多的工作。
阅读全文