回复 5楼 东海ECS
程序代码:
#include <iostream> #include <string> #include <thread> #include "SDL2/SDL.h" #include "SDL2/SDL_thread.h" extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswresample/swresample.h" #include "libavutil/time.h" #include "libswscale/swscale.h" #include "libavutil/imgutils.h" } const int kVideoWidth = 640; const int kVideoHeight = 360; const std::string kVideoPath = "test.mp4"; const std::string kOutputPath = "output.mp4"; const int kStartTime = 5; // 单位:秒 const int kEndTime = 10; // 单位:秒 int main(int argc, char* argv[]) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) { std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl; return -1; } AVFormatContext* format_context = avformat_alloc_context(); if (avformat_open_input(&format_context, kVideoPath.c_str(), nullptr, nullptr) != 0) { std::cerr << "Failed to open video file: " << kVideoPath << std::endl; return -1; } if (avformat_find_stream_info(format_context, nullptr) < 0) { std::cerr << "Failed to find video stream information" << std::endl; return -1; } const AVCodec* codec = nullptr; int stream_index = -1; for (int i = 0; i < format_context->nb_streams; i++) { if (format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { codec = avcodec_find_decoder(format_context->streams[i]->codecpar->codec_id); stream_index = i; break; } } if (codec == nullptr) { std::cerr << "Failed to find video codec" << std::endl; return -1; } AVCodecContext* codec_context = avcodec_alloc_context3(codec); if (avcodec_parameters_to_context(codec_context, format_context->streams[stream_index]->codecpar) < 0) { std::cerr << "Failed to copy video codec parameters to context" << std::endl; return -1; } if (avcodec_open2(codec_context, codec, nullptr) < 0) { std::cerr << "Failed to open video codec" << std::endl; return -1; } AVFrame* frame = av_frame_alloc(); AVFrame* frame_rgb = av_frame_alloc(); uint8_t* buffer = nullptr; int buffer_size = 0; buffer_size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1); buffer = reinterpret_cast<uint8_t*>(av_malloc(buffer_size)); av_image_fill_arrays(frame_rgb->data, frame_rgb->linesize, buffer, AV_PIX_FMT_RGB24, kVideoWidth, kVideoHeight, 1); struct SwsContext* sws_context = sws_getContext(codec_context->width, codec_context->height, codec_context->pix_fmt, kVideoWidth, kVideoHeight, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr); SDL_Window* window = SDL_CreateWindow("Video Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, kVideoWidth, kVideoHeight, SDL_WINDOW_OPENGL); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, kVideoWidth, kVideoHeight); AVPacket packet; AVFormatContext* output_format_context = nullptr; if (avformat_alloc_output_context2(&output_format_context, nullptr, nullptr, kOutputPath.c_str()) < 0) { std::cerr << "Failed to allocate output format context" << std::endl; return -1; } AVStream* output_stream = avformat_new_stream(output_format_context, codec); if (output_stream == nullptr) { std::cerr << "Failed to allocate output stream" << std::endl; return -1; } if (avcodec_parameters_copy(output_stream->codecpar, format_context->streams[stream_index]->codecpar) < 0) { std::cerr << "Failed to copy codec parameters to output stream" << std::endl; return -1; } output_stream->time_base = format_context->streams[stream_index]->time_base; if (!(output_format_context->oformat->flags & AVFMT_NOFILE)) { if (avio_open(&output_format_context->pb, kOutputPath.c_str(), AVIO_FLAG_WRITE) < 0) { std::cerr << "Failed to open output file" << std::endl; return -1; } } if (avformat_write_header(output_format_context, nullptr) < 0) { std::cerr << "Failed to write output file header" << std::endl; return -1; } bool is_running = true; int64_t start_pts = kStartTime * AV_TIME_BASE; int64_t end_pts = kEndTime * AV_TIME_BASE; while (av_read_frame(format_context, &packet) >= 0 && is_running) { if (packet.stream_index == stream_index) { if (avcodec_send_packet(codec_context, &packet) == 0) { while (avcodec_receive_frame(codec_context, frame) == 0) { if (frame->pts >= start_pts && frame->pts <= end_pts) { sws_scale(sws_context, frame->data, frame->linesize, 0, codec_context->height, frame_rgb->data, frame_rgb->linesize); SDL_UpdateTexture(texture, nullptr, frame_rgb->data[0], frame_rgb->linesize[0]); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_RenderPresent(renderer); if (av_write_frame(output_format_context, &packet) < 0) { std::cerr << "Failed to write frame to output file" << std::endl; return -1; } if (av_gettime_relative() >= end_pts) { is_running = false; break; } } } } } av_packet_unref(&packet); } av_write_trailer(output_format_context); av_frame_free(&frame); av_frame_free(&frame_rgb); avcodec_close(codec_context); avformat_close_input(&format_context); avformat_free_context(format_context); av_free(buffer); avio_close(output_format_context->pb); avformat_free_context(output_format_context); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
剪辑10秒钟视频 大小才1K。。。。
播放器 没有音频 2分4.86秒的视频。 50秒就播放完成了。。。。
你是不是要告诉我,代码如果拿到手,就可以正常使用,我就什么知识点也学不到了。。。。
写出了程序流程,让我自己找错误,这样才能更好地学习。。。。