2021-07-24 rv1126 nv12采集保存为 jpeg

1/打完收工,修补下就ok了

在这里插入图片描述

在这里插入图片描述

合成版

// Copyright 2020 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include <string>
#include <iostream>
#include <fstream>

 #include <pthread.h>

//#include "common/sample_common.h"
#include "rkmedia_api.h"
#include "rkmedia_venc.h"

static bool quit = false;

// 信号处理程序
static void sigterm_handler(int sig)
{
fprintf(stderr, "signal %d\n", sig);
quit = true;
}

//YUV转jpeg
static uint32_t yuv420sp_to_jpg(int width, int height, unsigned char *inputYuv,unsigned char *outJpeg)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
int i = 0, j = 0;
unsigned char *pY, *pU, *pV;
unsigned char yuvbuf[width * 3];
unsigned long outSize;
cinfo.err = jpeg_std_error(&jerr);//用于错误信息
jpeg_create_compress(&cinfo);  //初始化压缩对象
jpeg_mem_dest(&cinfo, &outJpeg, &outSize);
cinfo.image_width = width;//设置输入图片宽度
cinfo.image_height = height;//设置图片高度
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;//设置输入图片的格式,支持RGB/YUV/YCC等等
cinfo.dct_method = JDCT_FLOAT;
jpeg_set_defaults(&cinfo);//其它参数设置为默认的!
jpeg_set_quality(&cinfo, 40, TRUE);//设置转化图片质量,范围0-100
jpeg_start_compress(&cinfo, TRUE);
pY = inputYuv ;
pU = inputYuv +1 ;
pV = inputYuv + 3;
j = 1;
while (cinfo.next_scanline < cinfo.image_height) {
	int index = 0;
	for (i = 0; i < width; i += 2){//输入的YUV图片格式为标准的YUV444格式,所以需要把YUV420转化成YUV444.
		yuvbuf[index++] = *pY;
		yuvbuf[index++] = *pU;
		yuvbuf[index++] = *pV;
		pY += 2;
		yuvbuf[index++] = *pY;
		yuvbuf[index++] = *pU;
		yuvbuf[index++] = *pV;
		pY += 2;
		pU += 4;
		pV += 4;
	}
	row_pointer[0] = yuvbuf;
	(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);//单行图片转换压缩
	j++;
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);

return (uint32_t)outSize;
}


// 图像数据处理线程
static void *GetMediaBuffer(void *arg)
{
RGA_CHN rga_chn = *(RGA_CHN *)arg;
char save_path[512];

//
printf("#Start %s thread, rga_chn:%d\n", __func__, rga_chn);
//sprintf(save_path, "/userdata/output_%d.nv12", rga_chn);
//图片保存路径改到mmc 或者 tmp 目录
//sprintf(save_path, "/mnt/mmc/output_%d.nv12", rga_chn);
sprintf(save_path, "/tmp/output_%d.nv12", rga_chn);	
//
FILE *save_file = fopen(save_path, "w");
if (!save_file)
    printf("ERROR: Open %s failed!\n", save_path);

MEDIA_BUFFER mb = NULL;
int save_cnt = 0;
int recv_len;
while (!quit)
{
    mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA, rga_chn, 50);
    if (!mb)
    {
        if (!quit)
        {
            continue;
        }
        printf("chn-%d:RK_MPI_SYS_GetMediaBuffer get null buffer!\n", rga_chn);
        break;
    }

    recv_len = RK_MPI_MB_GetSize(mb);
    printf("Get Frame-chn-%d:ptr:%p, fd:%d, size:%zu, mode:%d, channel:%d, "
           "timestamp:%lld\n",
           rga_chn,
           RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb), recv_len,
           RK_MPI_MB_GetModeID(mb), RK_MPI_MB_GetChannelID(mb),
           RK_MPI_MB_GetTimestamp(mb));

    if (save_file && (save_cnt < 1))
    {
        int rtn = fwrite(RK_MPI_MB_GetPtr(mb), 1, recv_len, save_file);
        fsync(fileno(save_file));
        printf("#Save frame-chn-%d:%d to %s, rtn = %d\n", rga_chn, save_cnt, save_path, rtn);
        save_cnt++;
    }

    RK_MPI_MB_ReleaseBuffer(mb);
}

if (save_file) //保存图片失败 关闭
    fclose(save_file);

//成功 打印信息
printf("%s-chn-%d - exit\r\n", __func__, rga_chn);

return NULL;
}

//
int main()
{
int ret = -1;
//
VI_PIPE vi_pipe_0 = 0;
VI_CHN vi_chn_1 = 1;
//
RGA_CHN rga_chn_0 = 0;
  // RGA_CHN rga_chn_1 = 1; 屏蔽缩放同旋转操作
 //  RGA_CHN rga_chn_2 = 2;

// 初始化mpi sys
RK_MPI_SYS_Init();

//
// 数据源,ISP20的输出:
// rkispp_m_bypass, 不支持设置分辨率,不支持缩放,         NV12/NV16/YUYV/FBC0/FBC2
// rkispp_scale0,   max width: 3264,最大支持 8 倍缩放, NV12/NV16/YUYV
// rkispp_scale1,   max width: 1280,最大支持 8 倍缩放, NV12/NV16/YUYV
// rkispp_scale2,   max width: 1280,最大支持 8 倍缩放, NV12/NV16/YUYV
//
VI_CHN_ATTR_S vi_chn_attr;
vi_chn_attr.pcVideoNode = "rkispp_scale0";
vi_chn_attr.u32BufCnt = 4;
vi_chn_attr.u32Width = 1920;
vi_chn_attr.u32Height = 1080;
vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
//
ret = RK_MPI_VI_SetChnAttr(vi_pipe_0, vi_chn_1, &vi_chn_attr);
ret |= RK_MPI_VI_EnableChn(vi_pipe_0, vi_chn_1);
if (ret)
{
    printf("Create vi[%d] failed! ret=%d\n", vi_chn_1, ret);
    return -1;
}

//
// 源数据配置
//
MPP_CHN_S stSrcChn;
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = vi_pipe_0;
stSrcChn.s32ChnId = vi_chn_1;

//
// 输出-0
// 格式转换 IMAGE_TYPE_NV12 -> IMAGE_TYPE_YUV420P
//
RGA_ATTR_S stRgaAttr_0;
stRgaAttr_0.bEnBufPool = RK_TRUE;
stRgaAttr_0.u16BufPoolCnt = 4;
stRgaAttr_0.u16Rotaion = 0;
stRgaAttr_0.stImgIn.u32X = 0;
stRgaAttr_0.stImgIn.u32Y = 0;
stRgaAttr_0.stImgIn.imgType = IMAGE_TYPE_NV12;
stRgaAttr_0.stImgIn.u32Width = 1920;
stRgaAttr_0.stImgIn.u32Height = 1080;
stRgaAttr_0.stImgIn.u32HorStride = 1920;
stRgaAttr_0.stImgIn.u32VirStride = 1080;
stRgaAttr_0.stImgOut.u32X = 0;
stRgaAttr_0.stImgOut.u32Y = 0;
stRgaAttr_0.stImgOut.imgType = IMAGE_TYPE_YUV420P;
stRgaAttr_0.stImgOut.u32Width = 1920;
stRgaAttr_0.stImgOut.u32Height = 1080;
stRgaAttr_0.stImgOut.u32HorStride = 1920;
stRgaAttr_0.stImgOut.u32VirStride = 1080;
//
ret = RK_MPI_RGA_CreateChn(rga_chn_0, &stRgaAttr_0);
if (ret)
{
    printf("Create rga[%d] falied! ret=%d\n", rga_chn_0, ret);
    goto EXIT_0;
}

//初始化线程0
pthread_t read_thread_0;
//创建并连接线程
pthread_create(&read_thread_0, NULL, GetMediaBuffer, &rga_chn_0);

//连接通道 
MPP_CHN_S stDestChn_0;
stDestChn_0.enModId = RK_ID_RGA;
stDestChn_0.s32DevId = 0;
stDestChn_0.s32ChnId = rga_chn_0;
//
ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn_0);
if (ret)
{
    printf("Bind vi[1] and rga[%d] failed! ret=%d\n", rga_chn_0, ret);
    goto EXIT_1;
}

//    //
//    // 输出-1
 //   // 旋转 270 度
//    // 缩放 1920 -> 960
//    // 缩放 1080 -> 544
//    // 格式转换 IMAGE_TYPE_NV12 -> IMAGE_TYPE_YUV420P
 //   // 旋转缩放后保存为 YUV420P
//    RGA_ATTR_S stRgaAttr_1;
 //   stRgaAttr_1.bEnBufPool = RK_TRUE;
//   stRgaAttr_1.u16BufPoolCnt = 4;
//    stRgaAttr_1.u16Rotaion = 270;
//    stRgaAttr_1.stImgIn.u32X = 0;
//    stRgaAttr_1.stImgIn.u32Y = 0;
//    stRgaAttr_1.stImgIn.imgType = IMAGE_TYPE_NV12;
//    stRgaAttr_1.stImgIn.u32Width = 1920;
//    stRgaAttr_1.stImgIn.u32Height = 1080;
//    stRgaAttr_1.stImgIn.u32HorStride = 1920;
//    stRgaAttr_1.stImgIn.u32VirStride = 1080;
//    stRgaAttr_1.stImgOut.u32X = 0;
//    stRgaAttr_1.stImgOut.u32Y = 0;
//    stRgaAttr_1.stImgOut.imgType = IMAGE_TYPE_YUV420P;
//    stRgaAttr_1.stImgOut.u32Width = 544;
//    stRgaAttr_1.stImgOut.u32Height = 960;
//    stRgaAttr_1.stImgOut.u32HorStride = 544;
 //   stRgaAttr_1.stImgOut.u32VirStride = 960;
//
//    ret = RK_MPI_RGA_CreateChn(rga_chn_1, &stRgaAttr_1);
//    if (ret)
//    {
//        printf("Create rga[%d] falied! ret=%d\n", rga_chn_1, ret);
//        goto EXIT_2;
//    }

 //   pthread_t read_thread_1;
 //   pthread_create(&read_thread_1, NULL, GetMediaBuffer, &rga_chn_1);

//
//   MPP_CHN_S stDestChn_1;
//   stDestChn_1.enModId = RK_ID_RGA;
//    stDestChn_1.s32DevId = 0;
//    stDestChn_1.s32ChnId = rga_chn_1;
//
//    ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn_1);
//    if (ret)
//    {
//        printf("Bind vi[1] and rga[%d] failed! ret=%d\n", rga_chn_1, ret);
//        goto EXIT_3;
//    }

//
// 输出-2
// 裁剪 1920 -> 1000, 取中间部分
// 裁剪 1080 -> 800, 取中间部分
// 格式转换 IMAGE_TYPE_NV12 -> IMAGE_TYPE_YUV420P
// 取中间后保存为 YUV420P
   RGA_ATTR_S stRgaAttr_2;
//   stRgaAttr_2.bEnBufPool = RK_TRUE;
//    stRgaAttr_2.u16BufPoolCnt = 4;
//    stRgaAttr_2.u16Rotaion = 0;
 //   stRgaAttr_2.stImgIn.u32X = 460;
//    stRgaAttr_2.stImgIn.u32Y = 140;
//    stRgaAttr_2.stImgIn.imgType = IMAGE_TYPE_NV12;
 //   stRgaAttr_2.stImgIn.u32Width = 1000;
 //   stRgaAttr_2.stImgIn.u32Height = 800;
 //   stRgaAttr_2.stImgIn.u32HorStride = 1920;
 //   stRgaAttr_2.stImgIn.u32VirStride = 1080;
//   stRgaAttr_2.stImgOut.u32X = 0;
 //   stRgaAttr_2.stImgOut.u32Y = 0;
//    stRgaAttr_2.stImgOut.imgType = IMAGE_TYPE_YUV420P;
//    stRgaAttr_2.stImgOut.u32Width = 1000;
//    stRgaAttr_2.stImgOut.u32Height = 800;
//    stRgaAttr_2.stImgOut.u32HorStride = 1000;
//    stRgaAttr_2.stImgOut.u32VirStride = 800;
//
 //   ret = RK_MPI_RGA_CreateChn(rga_chn_2, &stRgaAttr_2);
 //   if (ret)
 //   {
 //       printf("Create rga[%d] falied! ret=%d\n", rga_chn_2, ret);
 //       goto EXIT_4;
//    }

//    pthread_t read_thread_2;
//    pthread_create(&read_thread_2, NULL, GetMediaBuffer, &rga_chn_2);

//
 //   MPP_CHN_S stDestChn_2;
 //   stDestChn_2.enModId = RK_ID_RGA;
 //   stDestChn_2.s32DevId = 0;
 //   stDestChn_2.s32ChnId = rga_chn_2;
//
 //   ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn_2);
//   if (ret)
//   {
 //      printf("Bind vi[1] and rga[%d] failed! ret=%d\n", rga_chn_2, ret);
 //      goto EXIT_5;
//   }

//
// 监听退出信号
//
printf("%s initial finish\n", __func__);
signal(SIGINT, sigterm_handler);

//
// 等待退出信号
// 没退出信号执行延时 100us
  // while (!quit)
 // {
  //     usleep(100);
  // }

//
// 退出
//
usleep(100);

yuv420sp_to_jpg();

ret = 0;

EXIT_6:
RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn_2);
EXIT_5:
RK_MPI_RGA_DestroyChn(rga_chn_2);
EXIT_4:
RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn_1);
EXIT_3:
RK_MPI_RGA_DestroyChn(rga_chn_1);
EXIT_2:
RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn_0);
EXIT_1:
RK_MPI_RGA_DestroyChn(rga_chn_0);
EXIT_0:
RK_MPI_VI_DisableChn(vi_pipe_0, vi_chn_1);

return ret;
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值