市面上比較流行的飛凌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文件需要重新初始化攝像頭。
因此,如果要重複壓縮視頻只需簡單地將這句刪除即可。