c语言实现给yuv文件添加帧序号

这是我14年刚工作时候写的代码。当时领导提出给yuv文件加帧序号,我就实现了这么一个算法。后来其实也没怎么用过,但是实现的思路挺有意思的。无意中给翻出来了,挂到网上来,更新一下我许久都没有更新的博客。。。。
先看图
这里写图片描述
这里写图片描述
main函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "fun.h"


int main(int argc, char *argv[])
{
    char InputVideoName[100];
    char OutputVideoName[100];
    int width;
    int height;
    int FrameNum;
    enum VideoFormat format = YUV444;
    enum NumColor color = BLACK;
    enum NumPosition position = LeftBottom;
    YuvVideoFrame yuv_video_frame;
    time_t start_time, end_time;
    FILE *ifp, *ofp;
    int y_pixel_num, u_pixel_num, v_pixel_num;
    struct NumColorInfo num_color_info;
    struct LineInfo line_info;
    int x, y; // 数字的位置坐标

    if(argc != 9)
    {
        printf("Error!\n");
        return -1;
    }
    strcpy(InputVideoName, argv[1]);
    strcpy(OutputVideoName, argv[2]);
    width = atoi(argv[3]);
    height = atoi(argv[4]);
    FrameNum = atoi(argv[5]); // 帧数
    format = (enum VideoFormat)atoi(argv[6]); // 格式 0表示yuv444,1表示yuv420 planar, 2表示yuv422 planar
    color = (enum NumColor)atoi(argv[7]); // 字体颜色 0表示黑色,1表示白色,2表示红色,3表示绿色,4表示蓝色
    position = (enum NumPosition)atoi(argv[8]); // 帧序号的位置 0表示左上角,1表示右上角,2表示左下角,3表示右下角

    start_time = time(NULL);

    // 初始化帧
    yuv_video_frame = (YuvVideoFrame)malloc(sizeof(struct YuvFrame));
    if(NULL == yuv_video_frame)
    {
        printf("run out of memory\n");
        exit(0);
    }
    InitializeFrame(width, height, format, yuv_video_frame);

    // 初始化颜色信息
    InitializeNumColorInfo(color, num_color_info);

    // 初始化数字线条和起始位置信息
    InitializeLineAndPositionInfo(width, height, position, line_info, x, y);

    // 打开输入输出文件
    if((ifp = fopen(InputVideoName, "rb")) == NULL)
    {
        printf("cannot open %s\n", InputVideoName);
        return -1;
    }
    if((ofp = fopen(OutputVideoName, "ab")) == NULL)
    {
        printf("cannot open %s\n", OutputVideoName);
        return -1;
    }

    y_pixel_num = width * height;
    switch(yuv_video_frame->format)
    {
        case YUV444: 
            u_pixel_num = y_pixel_num;
            v_pixel_num = y_pixel_num;
            break;
        case YUV420:
            u_pixel_num = y_pixel_num / 4;
            v_pixel_num = y_pixel_num / 4;
            break;
        case YUV422:
            u_pixel_num = y_pixel_num / 2;
            v_pixel_num = y_pixel_num / 2;
            break;
        default:
            break;
    }

    for(int frame_num = 0; frame_num < FrameNum; frame_num++)
    {
        fread(yuv_video_frame->y_component, sizeof(uchar), y_pixel_num, ifp);
        fread(yuv_video_frame->u_component, sizeof(uchar), u_pixel_num, ifp);
        fread(yuv_video_frame->v_component, sizeof(uchar), v_pixel_num, ifp);

        AddNumInYuvVideo(frame_num, x, y, line_info, num_color_info, yuv_video_frame);

        fwrite(yuv_video_frame->y_component, sizeof(uchar), y_pixel_num, ofp);
        fwrite(yuv_video_frame->u_component, sizeof(uchar), u_pixel_num, ofp);
        fwrite(yuv_video_frame->v_component, sizeof(uchar), v_pixel_num, ofp);
    }
    fclose(ifp);
    fclose(ofp);
    DisposeFrame(yuv_video_frame);

    end_time = time(NULL);
    //printf("\ntime = %d\n", end_time - start_time);

    return 0;
}

头文件 fun.h



enum VideoFormat{YUV444, YUV420, YUV422};  // 视频格式
enum NumColor{BLACK, WHITE, RED, GREEN, BLUE}; // 数字颜色
enum NumPosition{LeftTop, RightTop, LeftBottom, RightBottom}; // 数字的位置
typedef unsigned char uchar;
typedef struct YuvFrame *YuvVideoFrame;


#define MAX(a, b)  ((a) > (b) ? (a) : (b))

// YUV视频帧
struct YuvFrame
{
    int width; // 视频帧宽
    int height; // 视频帧高
    enum VideoFormat format; // 视频的格式
    uchar *y_component; // y分量
    uchar *u_component; // u分量
    uchar *v_component; // v分量
};

// 数字颜色信息
struct NumColorInfo
{
    uchar y_value;
    uchar u_value;
    uchar v_value;
};

// 数字线条信息
struct LineInfo
{
    int length; // 线条长
    int width; // 线条宽
};




// 将字符串转换为数字
int atoi(char *s);

/****************************************************************************
InitializeFrame:
    初始化视频帧
input:
    int width 视频帧的宽
    int height 视频帧的高
    enum VideoFormat format 视频的格式
output:
    YuvVideoFrame yuv_video_frame
return:
****************************************************************************/
void InitializeFrame(int width, int height, enum VideoFormat format, YuvVideoFrame yuv_video_frame);

/****************************************************************************
DisposeFrame:
    释放视频帧
input:
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void DisposeFrame(YuvVideoFrame yuv_video_frame);

/****************************************************************************
AddLine:
    在YUV视频帧上添加线条
input:
    int x 位置坐标
    int y 
    int width 添加线条的宽
    int height 添加线条的高 
    struct NumColorInfo num_color_info  数字的颜色
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void AddLine(int x, int y, 
             int width, int height, 
             struct NumColorInfo num_color_info,
             YuvVideoFrame yuv_video_frame);

/****************************************************************************
AddDigit:
    在YUV视频上添加数字
input:
    int digit 添加数字
    int x 位置坐标
    int y 
    struct LineInfo info_line 数字线条信息
    struct NumColorInfo num_color_info 数字颜色
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void AddDigit(int digit,
              int x, int y, 
              struct LineInfo info_line,
              struct NumColorInfo num_color_info,
              YuvVideoFrame yuv_video_frame);

/****************************************************************************
AddNumInYuvVideo:
    在YUV视频上添加帧序号
input:
    int frame_num  帧序号
    int x 数字起始位置坐标
    int y  
    struct LineInfo line_info  数字线条信息
    struct NumColorInfo num_color_info  颜色信息
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void AddNumInYuvVideo(int frame_num, int x, int y, struct LineInfo line_info, struct NumColorInfo num_color_info, YuvVideoFrame yuv_video_frame);

/****************************************************************************
InitializeNumColorInfo:
    初始化数字的颜色信息
input:
    enum NumColor color
output:
    struct NumColorInfo &num_color_info
return:
****************************************************************************/
void InitializeNumColorInfo(enum NumColor color, struct NumColorInfo &num_color_info);

/****************************************************************************
InitializeLineAndPositionInfo:
    初始化线条和位置信息
input:
    int width  视频帧宽
    int height  视频帧高
    enum NumPosition position
output:
    struct LineInfo &line_info 线条信息
    int &x 数字起始坐标
    int &y
return:
****************************************************************************/
void InitializeLineAndPositionInfo(int width, int height, enum NumPosition position, struct LineInfo &line_info, int &x, int &y);

调用的函数,文件fun.cpp

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "fun.h"


// 将字符串转换为数字
int atoi(char *s)
{
    int sign;
    int n;

    while(*s == ' ')
        s++;
    sign = (*s == '-') ? -1 : 1;
    if('-' == *s || '+' == *s)
        s++;
    for(n = 0; isdigit(*s); s++)
    {
        n = n * 10 + (*s - '0');
    }
    return n * sign;
}

/****************************************************************************
InitializeFrame:
    初始化视频帧
input:
    int width 视频帧的宽
    int height 视频帧的高
    enum VideoFormat format 视频的格式
output:
    YuvVideoFrame yuv_video_frame
return:
****************************************************************************/
void InitializeFrame(int width, int height, enum VideoFormat format, YuvVideoFrame yuv_video_frame)
{
    int y_pixel_num, u_pixel_num, v_pixel_num;

    yuv_video_frame->width = width;
    yuv_video_frame->height = height;
    yuv_video_frame->format = format;

    y_pixel_num = width * height;
    switch(format)
    {
    case YUV444:
        u_pixel_num = width * height;
        v_pixel_num = width * height;
        break;
    case YUV420:
        u_pixel_num = width * height / 4;
        v_pixel_num = width * height / 4;
        break;
    case YUV422:
        u_pixel_num = width * height / 2;
        v_pixel_num = width * height / 2;
        break;
    default:
        break;
    }
    yuv_video_frame->y_component = (uchar *)malloc(y_pixel_num * sizeof(uchar));
    if(NULL == yuv_video_frame->y_component)
    {
        printf("run out of memory\n");
        exit(0);
    }
    yuv_video_frame->u_component = (uchar *)malloc(u_pixel_num * sizeof(uchar));
    if(NULL == yuv_video_frame->u_component)
    {
        printf("run out of memory\n");
        exit(0);
    }
    yuv_video_frame->v_component = (uchar *)malloc(v_pixel_num * sizeof(uchar));
    if(NULL == yuv_video_frame->v_component)
    {
        printf("run out of memory\n");
        exit(0);
    }
}

/****************************************************************************
DisposeFrame:
    释放视频帧
input:
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void DisposeFrame(YuvVideoFrame yuv_video_frame)
{
    free(yuv_video_frame->y_component);
    free(yuv_video_frame->u_component);
    free(yuv_video_frame->v_component);
    free(yuv_video_frame);
}

/****************************************************************************
AddLine:
    在YUV视频帧上添加线条
input:
    int x 位置坐标
    int y 
    int width 添加线条的宽
    int height 添加线条的高 
    struct NumColorInfo num_color_info  数字的颜色
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void AddLine(int x, int y, 
             int width, int height, 
             struct NumColorInfo num_color_info,
             YuvVideoFrame yuv_video_frame)
{
    int i, j;

    if(YUV444 == yuv_video_frame->format)
    {
        for(i = 0; i < height; i++)
        {
            for(j = 0; j < width; j++)
            {
                *(yuv_video_frame->y_component + (y + i) * yuv_video_frame->width + (x + j)) = num_color_info.y_value;
                *(yuv_video_frame->u_component + (y + i) * yuv_video_frame->width + (x + j)) = num_color_info.u_value;
                *(yuv_video_frame->v_component + (y + i) * yuv_video_frame->width + (x + j)) = num_color_info.v_value;
            }
        }
    }

    if(YUV420 == yuv_video_frame->format)
    {
        for(i = 0; i < height; i++)
        {
            for(j = 0; j < width; j++)
            {
                *(yuv_video_frame->y_component + (y + i) * yuv_video_frame->width + (x + j)) = num_color_info.y_value;
                *(yuv_video_frame->u_component + (y + i) / 2 * yuv_video_frame->width / 2 + (x + j) / 2) = num_color_info.u_value;
                *(yuv_video_frame->v_component + (y + i) / 2 * yuv_video_frame->width / 2 + (x + j) / 2) = num_color_info.v_value;
            }
        }
    }

    if(YUV422 == yuv_video_frame->format)
    {
        for(i = 0; i < height; i++)
        {
            for(j = 0; j < width; j++)
            {
                *(yuv_video_frame->y_component + (y + i) * yuv_video_frame->width + (x + j)) = num_color_info.y_value;
                *(yuv_video_frame->u_component + (y + i) * yuv_video_frame->width / 2 + (x + j) / 2) = num_color_info.u_value;
                *(yuv_video_frame->v_component + (y + i) * yuv_video_frame->width / 2 + (x + j) / 2) = num_color_info.v_value;
            }
        }
    }
}

/****************************************************************************
AddDigit:
    在YUV视频上添加数字
input:
    int digit 添加数字
    int x 位置坐标
    int y 
    struct LineInfo info_line 数字线条信息
    struct NumColorInfo num_color_info 数字颜色
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void AddDigit(int digit,
              int x, int y, 
              struct LineInfo info_line,
              struct NumColorInfo num_color_info,
              YuvVideoFrame yuv_video_frame)
{
    int line_width = info_line.width;
    int line_length = info_line.length;

    if(0 == digit || 4 == digit || 5 == digit || 6 == digit || 8 == digit || 9 == digit)
    {
        AddLine(x, y + line_width, line_width, line_length, num_color_info, yuv_video_frame);
    }
    if(0 == digit || 2 == digit || 6 == digit || 8 == digit)
    {
        AddLine(x, y + line_width * 2 + line_length, line_width, line_length, num_color_info, yuv_video_frame);
    }
    if(0 == digit || 1 == digit || 2 == digit || 3 == digit || 4 == digit || 7 == digit || 8 == digit || 9 == digit)
    {
        AddLine(x + line_width + line_length, y + line_width, line_width, line_length, num_color_info, yuv_video_frame);
    }
    if(0 == digit || 1 == digit || 3 == digit || 4 == digit || 5 == digit || 6 == digit || 7 == digit || 8 == digit || 9 == digit)
    {
        AddLine(x + line_width + line_length, y + line_width * 2 + line_length, line_width, line_length, num_color_info, yuv_video_frame);
    }
    if(0 == digit || 2 == digit || 3 == digit || 5 == digit || 6 == digit || 7 == digit || 8 == digit || 9 == digit)
    {
        AddLine(x + line_width, y, line_length, line_width, num_color_info, yuv_video_frame);
    }
    if(2 == digit || 3 == digit || 4 == digit || 5 == digit || 6 == digit || 8 == digit || 9 == digit)
    {
        AddLine(x + line_width, y + line_width + line_length, line_length, line_width, num_color_info, yuv_video_frame);
    }
    if(0 == digit || 2 == digit || 3 == digit || 5 == digit || 6 == digit || 8 == digit)
    {
        AddLine(x + line_width, y + line_width * 2 + line_length * 2, line_length, line_width, num_color_info, yuv_video_frame);
    }
}


/****************************************************************************
AddNumInYuvVideo:
    在YUV视频上添加帧序号
input:
    int frame_num  帧序号
    int x 数字起始位置坐标
    int y  
    struct LineInfo line_info  数字线条信息
    struct NumColorInfo num_color_info  颜色信息
    YuvVideoFrame yuv_video_frame
output:
return:
****************************************************************************/
void AddNumInYuvVideo(int frame_num, int x, int y, struct LineInfo line_info, struct NumColorInfo num_color_info, YuvVideoFrame yuv_video_frame)
{
    int distance;
    int i;
    int digit;

    distance = line_info.width * 6 + line_info.length;
    i = 0;
    do{
        digit = frame_num % 10;
        AddDigit(digit, x - i * distance, y, line_info, num_color_info, yuv_video_frame);
        i++;
    }while(frame_num /= 10);
}


/****************************************************************************
InitializeNumColorInfo:
    初始化数字的颜色信息
input:
    enum NumColor color
output:
    struct NumColorInfo &num_color_info
return:
****************************************************************************/
void InitializeNumColorInfo(enum NumColor color, struct NumColorInfo &num_color_info)
{
    switch(color)
    {
    case BLACK: // 黑色
        num_color_info.y_value = 16;
        num_color_info.u_value = 128;
        num_color_info.v_value = 128;
        break;
    case WHITE: // 白色
        num_color_info.y_value = 235;
        num_color_info.u_value = 128;
        num_color_info.v_value = 128;
        break;
    case RED:  // 红色
        num_color_info.y_value = 65;
        num_color_info.u_value = 100;
        num_color_info.v_value = 212;
        break;
    case GREEN: // 绿色
        num_color_info.y_value = 112;
        num_color_info.u_value = 72;
        num_color_info.v_value = 58;
        break;
    case BLUE: // 蓝色
        num_color_info.y_value = 35;
        num_color_info.u_value = 212;
        num_color_info.v_value = 114;
        break;
    default:  // 其他情况黑色
        num_color_info.y_value = 16;
        num_color_info.u_value = 128;
        num_color_info.v_value = 128;
        break;
    }
}

/****************************************************************************
InitializeLineAndPositionInfo:
    初始化线条和位置信息
input:
    int width  视频帧宽
    int height  视频帧高
    enum NumPosition position
output:
    struct LineInfo &line_info 线条信息
    int &x 数字起始坐标
    int &y
return:
****************************************************************************/
void InitializeLineAndPositionInfo(int width, int height, enum NumPosition position, struct LineInfo &line_info, int &x, int &y)
{
    line_info.length = width / 100;  // 线条的长度
    line_info.width = MAX(width / 400, 1);  // 线条的宽度

    // 数字的起始位置
    switch(position)
    {
    case LeftTop: // 左上角
        x = line_info.width * 22 + line_info.length * 3;
        y = line_info.width * 4;
        break;
    case RightTop: // 右上角
        x = width - line_info.width * 6 - line_info.length;
        y = line_info.width * 4;
        break;
    case LeftBottom: // 左下角
        x = line_info.width * 22 + line_info.length * 3;
        y = height - line_info.width * 7 - line_info.length * 2;
        break;
    case RightBottom: // 右下角
        x = width - line_info.width * 6 - line_info.length;
        y = height - line_info.width * 7 - line_info.length * 2;
        break;
    default:
        break;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值