zfec用例

※要求:

将一个视频文件分割成k个块,使用zfec库,编码出n个块,将这n个块当做n个文件记录在磁盘上。然后读取其中的n-2个文件,解码出新的视频文件,要能够顺利播放。提示:最后一个块剩余部分用全0补齐


编写代码的时候,我实际采用(4,8)编码,先将文件分块,再将每一块分成4份大小相同的原始数据块,调用库函数zfec生成4份检验块。


1.按4k大小分块

#include <stdlib.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "fec.h"

#define BUFSIZE (1024*4) 
//分块大小为4K
#define MOVIE_NAME "123.jpg"
#define file_target "target.jpg"
#define file_EC "EC.txt"

#define EC_K 4
#define EC_M 8
#define NR (EC_M - EC_K) 
#define SZ (BUFSIZE/EC_K) 
int main(int argv, char *argc[])
{
        int fd_target,fd_movie,fd_EC,i=0,j=0,num,ret;
	 unsigned long byte,byte_0;
        unsigned blocks[NR];
        fec_t *code;
        char buf[BUFSIZE] = {0};
        char dest[NR*SZ] = {0};
        char *src[EC_K];
        char *fecs[NR];
		
        for(i = 0; i < EC_K; i++)
             src[i] = buf + i*SZ;
        for(i = 0; i < NR; i++){
             blocks[i] = EC_K + i;
             fecs[i] = dest + i*SZ;
        }

        code = fec_new(EC_K, EC_M);
		
	  fd_movie = open(MOVIE_NAME,O_RDWR|O_APPEND|O_SYNC);
        fd_EC = open(file_EC,O_RDWR|O_APPEND|O_CREAT|O_SYNC);
        if(fd_movie < 0 || fd_target < 0 ){
             printf("file open failed!\n");
             return -1;
        }
		
	/* lseek( fd_movie, 0, SEEK_END );
       movie_size=ftell(fd_movie);*/
	 lseek( fd_movie, 0, SEEK_SET ); 
	 lseek( fd_EC, 0, SEEK_SET ); 
	 printf("init is succesful!\n");

	 
//encode
	while((byte = read(fd_movie,buf,BUFSIZE))>0){

		//最后一块用0  补齐
		
             fec_encode(code, (const gf*const*)src, (const gf*const*)fecs, blocks, NR, SZ);
             ret = write(fd_EC, buf, BUFSIZE);  
             if(ret < 0)
                 return -1;
             ret = write(fd_EC, dest, NR*SZ);  
             if(ret < 0)
                 return -1;
	
	      memset(buf,0,BUFSIZE);
		
        }
	 printf("encode is succeful ! \n");

	 
//decode,假设数据全部失效

        char *in_recovery[EC_K] = {fecs[0], fecs[1], fecs[2],fecs[3]};
        char buf_recovery[4*SZ];
        char *out_recovery[4] = {buf_recovery, buf_recovery+SZ,buf_recovery+2*SZ,buf_recovery+3*SZ};
        unsigned index[EC_K] = {4,5,6,7}; 

	  fd_target = open(file_target,O_RDWR|O_APPEND|O_CREAT|O_SYNC);
	  lseek( fd_EC, 0, SEEK_SET ); 
	  while(read (fd_EC,buf,BUFSIZE) > 0){
		 byte = read(fd_EC,dest,BUFSIZE);
		
		 if(byte!=BUFSIZE)
		 	return -1;
		 fec_decode(code, (const gf*const*)in_recovery, (const gf*const*)out_recovery, index, SZ);
		 ret=write(fd_target,buf_recovery,BUFSIZE);
		 if(ret < 0)
                 return -1;
		 memset(buf_recovery,0,BUFSIZE);
		
	  }
	  printf("decode is succeful ! \n");
	  
	  close(fd_target);
        close(fd_movie);
	  close(fd_EC);
	 
        return 0;
}


2.按4M大小分块

#include <stdlib.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include "fec.h"

#define BUFSIZE (1024*1024*4) 
//分块大小为4M
#define MOVIE_NAME "S01E01.mkv"
#define file_target "target.mkv"
#define file_EC "EC111.txt"

#define EC_K 4
#define EC_M 8
#define NR (EC_M - EC_K) 
#define SZ (BUFSIZE/EC_K) 
int main(int argv, char *argc[])
{
        int fd_target,fd_movie,fd_EC,i=0,j=0,num,ret;
	 unsigned long byte,byte_0;
        unsigned blocks[NR];
        fec_t *code;
        char *buf=(char*)malloc(BUFSIZE);
        char *dest=(char*)malloc(BUFSIZE);
        char *src[EC_K];
        char *fecs[NR];
		
        for(i = 0; i < EC_K; i++)
             src[i] = buf + i*SZ;
        for(i = 0; i < NR; i++){
             blocks[i] = EC_K + i;
             fecs[i] = dest + i*SZ;
        }

        code = fec_new(EC_K, EC_M);
		
	  fd_movie = open(MOVIE_NAME,O_RDWR|O_APPEND|O_SYNC);
        fd_EC = open(file_EC,O_RDWR|O_APPEND|O_CREAT|O_SYNC);
        if(fd_movie < 0 || fd_target < 0 ){
             printf("file open failed!\n");
             return -1;
        }
		
	/* lseek( fd_movie, 0, SEEK_END );
       movie_size=ftell(fd_movie);*/
	 lseek( fd_movie, 0, SEEK_SET ); 
	 lseek( fd_EC, 0, SEEK_SET ); 
	 printf("init is succesful!\n");

	 
//encode
	while((byte = read(fd_movie,buf,BUFSIZE))>0){

		//最后一块用0  补齐
		
             fec_encode(code, (const gf*const*)src, (const gf*const*)fecs, blocks, NR, SZ);
             ret = write(fd_EC, buf, BUFSIZE);  
             if(ret < 0)
                 return -1;
             ret = write(fd_EC, dest, NR*SZ);  
             if(ret < 0)
                 return -1;
	
	      memset(buf,0,BUFSIZE);
		
        }
	 printf("encode is succeful ! \n");

	 
//decode,假设数据全部失效

        char *in_recovery[EC_K] = {fecs[0], fecs[1], fecs[2],fecs[3]};
        char *buf_recovery=(char*)malloc(BUFSIZE);
        char *out_recovery[4] = {buf_recovery, buf_recovery+SZ,buf_recovery+2*SZ,buf_recovery+3*SZ};
        unsigned index[EC_K] = {4,5,6,7}; 

	  fd_target = open(file_target,O_RDWR|O_APPEND|O_CREAT|O_SYNC);
	  lseek( fd_EC, 0, SEEK_SET ); 
	  while(read (fd_EC,buf,BUFSIZE) > 0){
		 byte = read(fd_EC,dest,BUFSIZE);
		
		 if(byte!=BUFSIZE)
		 	return -1;
		 fec_decode(code, (const gf*const*)in_recovery, (const gf*const*)out_recovery, index, SZ);
		 ret=write(fd_target,buf_recovery,BUFSIZE);
		 if(ret < 0)
                 return -1;
		 memset(buf_recovery,0,BUFSIZE);
		
	  }
	  printf("decode is succeful ! \n");
	  free(buf);
	  free(dest);
	  free(buf_recovery);
	  
	  close(fd_target);
         close(fd_movie);
	  close(fd_EC);
	 
        return 0;
}


注:

1.我一开始用char buf[]设置缓冲区,大小为4k,对几十K大小的JPG文件进行操作时没有问题,速度挺快,然后试着对一首大小为5M的歌,发现需要点时间,如果再换成几百M的视频,那就要等很久了,所以我想将buf设大一点,变成4M。

然后我很熟练的将#define BUFSIZE (1024*4) 改成#define BUFSIZE (1024*1024*4) ,编译执行,段错误。想来是因为这个数组过大而引起的,所以还是老老实实用char *buf=(char*)malloc(BUFSIZE);

2.char a[5];char *b = a + 2;b指向的是a[2]。char *b = a ;等价于 char *b = &a[0];

3.字符指针移位的问题

char *p = "abcde";
*(p+1)= 'w';
编译通过,运行出错,为何?

 因为 p 没有分配内存,指向的是系统的内存,那段内存是只读的,因此改变那里的值是错误的

上面的可以理解为

const char a[] = "abcde";
char *p = a;
*(p+1) = 'w';  // 错误,因为a是const的,也就是只读的

char a[] = "abcde";
char *p = a;
*(p+1) = 'w';  // 这样是正确的,因为a那段内存是可写的

引用:

这个不好说,不能明确说它放在什么地方,给你举个例子吧,用指针来举个例子
定义一个字符串常量:char* p =  "what are doing?"
那么在这句话中,p和 "what are doing?"这两个是不在一个存储区上的,不过我认为字符串常量应该是存储在正文段和数据段之间,也有人说是放在静态存储区上,也有人说是放在rodata  只读数据段上,你可以自己从gdb上看一下。这里我给你一点资料你理解一下,我们一块学习啊


这里是几个存放数据的内存段:
1)正文段——CPU执行的机器指令部分;一个程序只有一个副本;只读,防止程序由于意外事故而修改自身指令; 
2)初始化数据段(数据段)——在程序中所有赋了初值的全局变量,存放在这里。 
3)非初始化数据段(bss段)——在程序中没有初始化的全局变量;内核将此段初始化为0。 
4)栈——增长方向:自顶向下增长;自动变量以及每次函数调用时所需要保存的信息(返回地址;环境信息)。 
5)堆——动态存储。


这里还有一段有个高人写的一段小程序,很详细的
 
//main.cpp   

int a = 0; 全局初始化区   
char *p1; 全局未初始化区   
main()   
{   
int b; 栈   
char s[] = "abc"; 栈   
char *p2; 栈   
char *p3 = "123456"; 123456\0在常量区,p3在栈上。   
static int c =0; 全局(静态)初始化区   
p1 = (char *)malloc(10);   
p2 = (char *)malloc(20);   
分配得来得10和20字节的区域就在堆区。   
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"
优化成一个地方。   

参考:http://zhidao.baidu.com/question/345236310.html




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值