市面上比较流行的飞凌OK6410A/飞凌OK6410B或者是友善之臂的arm11开发板亦或是华天正的arm11开发板使用的都是三星公司的32位CPU。
前阵子发现了这些开发板视频采集方面存在的共同Bug:当用MFC压缩摄像头采集的H264视频的时候,由于这些开发板用的是三星公司提供的摄像头压缩源码,这个源码存在一个Bug,在采集视频的时候输入“e”采集视频,输入“x”退出采集,可是连续采集视频的时候,也就是连续输入“e”时出现错误“segment…”。
首先三星的源码是:
while (1) {
key = getchar();
if(key == 'e')
encoding_flag = TRUE;
else if(key == 'x') {
finished = 1;
pthread_exit(0);
}
if (encoding_flag == TRUE) {
pthread_mutex_lock(&mutex);
handle = mfc_encoder_init(LCD_WIDTH, LCD_HEIGHT, 30, 1000, 30);
sprintf(&file_name[0], "Cam_encoding_%dx%d-%d.264", LCD_WIDTH, LCD_HEIGHT, ++film_cnt);
printf("Name of encoded file : Cam_encoding_%dx%d-%d.264\n", LCD_WIDTH, LCD_HEIGHT, film_cnt);
fflush(stdout);
/* file create/open, note to "wb" */
encoded_fp = fopen(&file_name[0], "wb");
if (!encoded_fp) {
perror(&file_name[0]);
}
/* Codec start */
start = 1;
ret = ioctl(cam_c_fp, VIDIOC_STREAMON, &start);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_STREAMON failed\n");
exit(1);
}
for(yuv_cnt=0; yuv_cnt < frame_num; yuv_cnt++){
frame_count++;
/* read from camera device */
if (read(cam_c_fp, g_yuv, YUV_FRAME_BUFFER_SIZE) < 0) {
perror("read()");
}
if(frame_count == 1)
encoded_buf = mfc_encoder_exe(handle, g_yuv, YUV_FRAME_BUFFER_SIZE, 1, &encoded_size);
else
encoded_buf = mfc_encoder_exe(handle, g_yuv, YUV_FRAME_BUFFER_SIZE, 0, &encoded_size);
fwrite(encoded_buf, 1, encoded_size, encoded_fp);
}
frame_count = 0;
/* Codec stop */
start = 0;
ret = ioctl(cam_c_fp, VIDIOC_STREAMOFF, &start);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_STREAMOFF failed\n");
exit(1);
}
printf("100 frames were encoded\n");
printf("\nSelect ==> ");
mfc_encoder_free(handle);
fclose(encoded_fp);
encoding_flag= FALSE;
pthread_mutex_unlock(&mutex);
}
}
上述源码将压缩好的数据写入文件,每次输入”e“则重新生成一个新文件,从中不难看出每次生成一个文件之后执行了:
ret = ioctl(cam_c_fp, VIDIOC_STREAMOFF, &start);
if (ret < 0) {
printf("V4L2 : ioctl on VIDIOC_STREAMOFF failed\n");
exit(1);
}
这段代码的作用是关闭视频流,这儿关闭了视频流之后实际上是关闭了摄像头,所以如果要再次输入”e“之后重新压缩视频成H264文件需要重新初始化摄像头。
因此,如果要重复压缩视频只需简单地将这句删除即可。