如果不是特别熟悉C/C++,又要使用FFmpeg.API处理一些简单的音视频业务,那么可以使用org.bytedeco:ffmpeg-platform,下面记录一下使用ffmpeg-platform视频解码的方法。
1. 代码实现
下面是一个将MP4中的视频数据解码出来并转化成RGB24格式的例子:
public class DecodeVideo { public static void main(String[] args) throws IOException { decode_video("t.mp4", "t.rgb24"); } public static void decode_video(String input, String output) throws IOException { AVFormatContext ifmt_ctx = new AVFormatContext(null); AVCodecContext ic = null; SwsContext sws_ctx = null; AVFrame frame = null; AVPacket pkt = null; PointerPointer<BytePointer> dst_data = new PointerPointer<>(1); IntPointer dst_linesize = new IntPointer(1); try (OutputStream os = new FileOutputStream(output)) { int ret = avformat_open_input(ifmt_ctx, input, null, null); if (ret < 0) { throw new IOException(ret + ":avformat_open_input error"); } ret = avformat_find_stream_info(ifmt_ctx, (AVDictionary) null); if (ret < 0) { throw new IOException(ret + ":avformat_find_stream_info error"); } int nb_streams = ifmt_ctx.nb_streams(); int video_index = -1; for (int i = 0; i < nb_streams; i++) { if (ifmt_ctx.streams(i).codecpar().codec_type() == AVMEDIA_TYPE_VIDEO) { video_index = i; break; } } if (video_index == -1) { throw new IOException("video index = -1"); } AVCodec codec = avcodec_find_decoder(ifmt_ctx.streams(video_index).codecpar().codec_id()); if (Objects.isNull(codec)) { throw new IOException("avcodec_find_decoder error"); } ic = avcodec_alloc_context3(codec); if (Objects.isNull(ic)) { throw new IOException("avcodec_alloc_context3 error"); } /* Copy codec parameters from input stream to output codec context */ ret = avcodec_parameters_to_context(ic, ifmt_ctx.streams(video_index).codecpar()); if (ret < 0) { throw new IOException(ret + ":avcodec_parameters_to_context error"); } ret = avcodec_open2(ic, codec, (AVDictionary) null); if (ret < 0) { throw new IOException(ret + "avcodec_open2 error"); } frame = av_frame_alloc(); if (Objects.isNull(frame)) { throw new IOException("av_frame_alloc"); } pkt = av_packet_alloc(); if (Objects.isNull(pkt)) { throw new IOException("av_packet_alloc error"); } sws_ctx = sws_getContext(ic.width(), ic.height(), ic.pix_fmt(), ic.width(), ic.height(), AV_PIX_FMT_RGB24, SWS_BICUBIC, null, null, (DoublePointer) null); if (Objects.isNull(sws_ctx)) { throw new IOException("sws_getContext error"); } ret = av_image_alloc(dst_data, dst_linesize, ic.width(), ic.height(), AV_PIX_FMT_RGB24, 1); if (ret < 0) { throw new IOException(ret + ":av_image_alloc error"); } byte[] buffer = new byte[ret]; while (true) { ret = av_read_frame(ifmt_ctx, pkt); if (ret == AVERROR_EAGAIN() || ret == AVERROR_EOF) { break; } else if (ret < 0) { throw new IOException(ret + ":av_read_frame error"); } if (pkt.stream_index() != video_index) { continue; } ret = avcodec_send_packet(ic, pkt); if (ret < 0) { throw new IOException(ret + ":avcodec_send_packet error"); } while (true) { ret = avcodec_receive_frame(ic, frame); if (ret == AVERROR_EAGAIN() || ret == AVERROR_EOF) { break; } else if (ret < 0) { throw new IOException(ret + ":avcodec_receive_frame error"); } sws_scale(sws_ctx, frame.data(), frame.linesize(), 0, ic.height(), dst_data, dst_linesize); dst_data.get(BytePointer.class, 0).get(buffer); os.write(buffer); } } System.out.printf( "Scaling succeeded. Play the output file with the command:\n" + "ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n", av_get_pix_fmt_name(AV_PIX_FMT_RGB24).getString(), ic.width(), ic.height(), output); } finally { dst_data.close(); dst_linesize.close(); if (Objects.nonNull(pkt)) { av_packet_free(pkt); } if (Objects.nonNull(frame)) { av_frame_free(frame); } if (Objects.nonNull(ic)) { avcodec_free_context(ic); } if (Objects.nonNull(sws_ctx)) { sws_freeContext(sws_ctx); } avformat_close_input(ifmt_ctx); } } }
2. 结果展示
转化的RGB24视频数据,有使用ffplay播放,效果如下:
播放命令:
ffplay -f rawvideo -pix_fmt rgb24 -video_size 352x288 t.rgb24
完整代码:扫描左侧头像小程序获取,或私信联系。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)