从 yuv file 中读取数据到avframe 的data 中;;;将avfreame 的data 写入 yuvfile 中;;;将avfreame 的data 写入 数组中

核心是一定要注意 有没有字节对齐问题。

从 yuv file 中读取数据到avframe 的data 中

核心是我们要知道 yuv file 的分辨率,假设是800x600的。还要知道 yuv file的 align,

那么create avframe的时候, 就能准备一个 好用的 avframe。

如下的例子是:我们要读取的yuv file 是 800x600 的,且align是1,align是1,对应的linesize[0] = 800

    //1.创建avframe
    AVFrame* avframe = av_frame_alloc();

    avframe->width = 800;
    avframe->height = 600;
    avframe->format = AV_PIX_FMT_YUV420P;

    avframe->linesize[0] = 800;
    avframe->linesize[1] = 400;
    avframe->linesize[2] = 400;
    avframe->pts = 0;

    ret = av_frame_get_buffer(avframe, 0);

    //6.给avframe中写数据,数据要从 这里读  

    //ifstream readfileifs("./111/800_600_yuv420p_25.yuv", ios_base::binary);
   

//7. 通过 av_image_get_buffer_size 方法,获取一张图片的大小
    int frame_bytes_bufsize = av_image_get_buffer_size(
        (enum AVPixelFormat)avframe->format,
        avframe->width,
        avframe->height,
        1);

    //分配对应大小的空间
    uint8_t* frame_bytes_buf = (uint8_t*)malloc(frame_bytes_bufsize);

        memset(frame_bytes_buf, 0, frame_bytes_bufsize);

//从yuv中读取这么大的数据
        readfileifs.read((char *)frame_bytes_buf, frame_bytes_bufsize);

//将 frame_bytes_buf 中的数据通过 av_image_fill_arrays方法,给avframe的data 和 avframe的linesize 赋值。这样就能得到

        int need_size = av_image_fill_arrays(avframe->data,
            avframe->linesize,
            frame_bytes_buf,
            (enum AVPixelFormat)avframe->format,
            avframe->width,
            avframe->height,
            1);

将avfreame 的data 写入 yuvfile 中

 NV12

				if (send_avframe->linesize[0] == send_avframe->width) {
					//没有字节对齐问题
					writefstream.write((char*)send_avframe->data[0], send_avframe->linesize[0] * send_avframe->height);
					writefstream.write((char*)send_avframe->data[1], send_avframe->linesize[1] * send_avframe->height / 2);
				}
				else {
					//有字节对齐问题时候的处理
					for (int j = 0; j < send_avframe->height; j++) {
						writefstream.write((char*)(send_avframe->data[0] + j * send_avframe->linesize[0]), send_avframe->width);
					}
					for (int j = 0; j < avframe->height / 2; j++) {
						writefstream.write((char*)(send_avframe->data[1] + j * send_avframe->linesize[1]), send_avframe->width);
					}
				}

yuv420p

if (send_avframe->linesize[0] == send_avframe->width) {
					//没有字节对齐问题
					writefstream.write((char*)send_avframe->data[0], send_avframe->linesize[0] * send_avframe->height);
					writefstream.write((char*)send_avframe->data[1], send_avframe->linesize[1] * send_avframe->height / 2);
					writefstream.write((char*)send_avframe->data[2], send_avframe->linesize[2] * send_avframe->height / 2);
				}
				else {
					//有字节对齐问题时候的处理
					// 先写完Y,再写U,再写V
					for (int j = 0; j < send_avframe->height; j++) {
						writefstream.write((char*)(send_avframe->data[0] + j * send_avframe->linesize[0]), send_avframe->width);
					}
					for (int j = 0; j < avframe->height / 2; j++) {
						writefstream.write((char*)(send_avframe->data[1] + j * send_avframe->linesize[1]), send_avframe->width / 2);
					}
					for (int j = 0; j < avframe->height / 2; j++) {
						writefstream.write((char*)(send_avframe->data[2] + j * send_avframe->linesize[2]), send_avframe->width / 2);
					}
				}

将avfreame 的data 写入 数组中

 从 avframe 的data 中读取数据到 数组中

NV12_data_ = new uint8_t[4096 * 2160 * 1.5];

if (frame->linesize[0] == frame->width)
		{
			// 如果没有字节对齐问题,直接先copy avframe->data[0];然后再copy avframe->data[1]
			memcpy(NV12_data_, frame->data[0], frame->linesize[0] * frame->height); //Y
			memcpy(NV12_data_ + frame->linesize[0] * frame->height, frame->data[1], frame->linesize[1] * frame->height / 2); //UV
		}
		else //逐行复制
		{
			//这里字节有对齐问题的时候,为什么要这样 copy 呢?
			//而且实验测试,当 avframe是 400 * 300 时候,字节对齐有问题时候,就是用这种方法就能解决。
			for (int i = 0; i < frame->height; i++) //Y
			{
				memcpy(NV12_data_ + i * frame->width,
					frame->data[0] + i * frame->linesize[0],
					frame->width
				);
			}
			for (int i = 0; i < frame->height / 2; i++)  //UV
			{
				auto p = NV12_data_ + frame->height * frame->width;// 移位Y
				memcpy(p + i * frame->width,
					frame->data[1] + i * frame->linesize[1],
					frame->width
				);
			}
		}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值