※要求:
将一个视频文件分割成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