Android ffmpeg yuv原始数据写入yuv文件

1.首先要给yuv数据分配缓存空间
u_int8_t *video_dst_data[4];
int video_dst_linesize[4];
int video_dst_bufsize;
video_dst_bufsize=av_image_alloc(video_dst_data,video_dst_linesize,dec_ctx->width,dec_ctx->height,pixelFormat,1);
2.
// 循环读取一帧视频
while (av_read_frame(fmt_ctx, &avPacket) >= 0) {
//判断是否为视频流
if (avPacket.stream_index == videoStream->index) {
LOGE(“AVStream is VideoStream”);
got_frame = 0;
//对该帧进行解码
ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &avPacket);
if (ret < 0) {
LOGE(“Error decoding video\n ret=%d”, ret);
break;
}
if (got_frame) {
//把解码后视频帧添加到filter graph
if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) <
0) {
LOGE(“Error while feeding the filter_graph\n”);
break;
}
//把滤波后的视频帧从filter graph取出来

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要将 YUV 数据编码为视频文件,可以使用 ffmpeg 库提供的 API。以下是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <libavutil/imgutils.h> #include <libavutil/opt.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> int main(int argc, char *argv[]) { int ret = 0; AVFormatContext *format_ctx = NULL; AVOutputFormat *output_fmt = NULL; AVStream *video_stream = NULL; AVCodec *codec = NULL; AVCodecContext *codec_ctx = NULL; AVPacket pkt = { 0 }; int video_frame_count = 0; int video_width = 640; int video_height = 480; int video_fps = 25; const char *output_filename = "output.mp4"; // 初始化 FFmpeg 库 av_register_all(); // 打开输出文件 ret = avformat_alloc_output_context2(&format_ctx, NULL, NULL, output_filename); if (ret < 0) { fprintf(stderr, "Failed to allocate output format context: %s\n", av_err2str(ret)); return ret; } output_fmt = format_ctx->oformat; // 添加视频流 codec = avcodec_find_encoder(output_fmt->video_codec); if (!codec) { fprintf(stderr, "Failed to find video encoder\n"); ret = AVERROR(EINVAL); goto end; } video_stream = avformat_new_stream(format_ctx, codec); if (!video_stream) { fprintf(stderr, "Failed to create video stream\n"); ret = AVERROR(EINVAL); goto end; } codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { fprintf(stderr, "Failed to allocate codec context\n"); ret = AVERROR(ENOMEM); goto end; } codec_ctx->width = video_width; codec_ctx->height = video_height; codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; codec_ctx->time_base = (AVRational) { 1, video_fps }; codec_ctx->framerate = (AVRational) { video_fps, 1 }; codec_ctx->gop_size = 10; codec_ctx->max_b_frames = 1; codec_ctx->bit_rate = 400000; codec_ctx->rc_min_rate = codec_ctx->rc_max_rate = codec_ctx->bit_rate; codec_ctx->sample_aspect_ratio = (AVRational) { 1, 1 }; if (format_ctx->oformat->flags & AVFMT_GLOBALHEADER) codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; ret = avcodec_open2(codec_ctx, codec, NULL); if (ret < 0) { fprintf(stderr, "Failed to open video encoder: %s\n", av_err2str(ret)); goto end; } ret = avcodec_parameters_from_context(video_stream->codecpar, codec_ctx); if (ret < 0) { fprintf(stderr, "Failed to copy codec parameters: %s\n", av_err2str(ret)); goto end; } av_dump_format(format_ctx, 0, output_filename, 1); // 打开输出文件并写文件头 ret = avio_open(&format_ctx->pb, output_filename, AVIO_FLAG_WRITE); if (ret < 0) { fprintf(stderr, "Failed to open output file: %s\n", av_err2str(ret)); goto end; } ret = avformat_write_header(format_ctx, NULL); if (ret < 0) { fprintf(stderr, "Failed to write file header: %s\n", av_err2str(ret)); goto end; } // 编码 YUV 数据并写入文件 int y_size = video_width * video_height; int uv_size = y_size / 4; uint8_t *y_data = (uint8_t *) malloc(y_size); uint8_t *u_data = (uint8_t *) malloc(uv_size); uint8_t *v_data = (uint8_t *) malloc(uv_size); for (int i = 0; i < 300; i++) { // 生成测试数据 for (int j = 0; j < y_size; j++) { y_data[j] = i % 255; } for (int j = 0; j < uv_size; j++) { u_data[j] = (i + j) % 255; v_data[j] = (i + j + uv_size) % 255; } // 将 YUV 数据填充到 AVFrame 中 AVFrame *frame = av_frame_alloc(); frame->width = video_width; frame->height = video_height; frame->format = AV_PIX_FMT_YUV420P; av_image_fill_arrays(frame->data, frame->linesize, y_data, video_width, u_data, video_width / 2, v_data, video_width / 2, AV_PIX_FMT_YUV420P, 1); // 编码 AVFrame写入文件 ret = avcodec_send_frame(codec_ctx, frame); if (ret < 0) { fprintf(stderr, "Error sending frame: %s\n", av_err2str(ret)); av_frame_free(&frame); goto end; } while (ret >= 0) { ret = avcodec_receive_packet(codec_ctx, &pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { fprintf(stderr, "Error receiving packet: %s\n", av_err2str(ret)); goto end; } pkt.stream_index = video_stream->index; av_packet_rescale_ts(&pkt, codec_ctx->time_base, video_stream->time_base); pkt.pts = video_frame_count * video_stream->time_base.den / (video_stream->time_base.num * video_fps); pkt.dts = pkt.pts; pkt.duration = video_stream->time_base.den / (video_stream->time_base.num * video_fps); pkt.pos = -1; av_interleaved_write_frame(format_ctx, &pkt); av_packet_unref(&pkt); } av_frame_free(&frame); video_frame_count++; } // 写文件尾并释放资源 av_write_trailer(format_ctx); end: if (codec_ctx) { avcodec_free_context(&codec_ctx); } if (format_ctx) { if (format_ctx->pb) { avio_closep(&format_ctx->pb); } avformat_free_context(format_ctx); } if (ret < 0) { fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); return 1; } return 0; } ``` 在这个示例代码中,我们首先使用 avformat_alloc_output_context2 函数创建一个 AVFormatContext 对象,然后使用 avformat_new_stream 函数为该对象添加一个视频流。接着,我们使用 AVCodecContext 结构体设置了视频流的一些参数,例如分辨率、帧率、编码格式等。然后,我们使用 avcodec_open2 函数打开了该编码器,并使用 avcodec_parameters_from_context 函数将编码器参数复制到视频流的 codecpar 结构体中。最后,我们打开输出文件写入文件头,然后循环编码 YUV 数据并将编码后的数据写入文件中,最后写入文件尾并释放资源。 需要注意的是,在编码每一帧数据时,我们需要将 AVFrame 转换成编码器所需的格式,并使用 avcodec_send_frame 函数发送该 AVFrame,然后使用 avcodec_receive_packet 函数接收编码器编码后的数据。在将编码后的数据写入文件前,需要将编码后的时间戳 PTS 和 DTS 进行适当的转换和设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安卓兼职framework应用工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值