📄 vid_avi.c
字号:
/*****************************************************************************
* FUNCTION
* med_avi_seek_by_time
* DESCRIPTION
*
* PARAMETERS
* time_in_ms [IN]
* RETURNS
*
*****************************************************************************/
kal_int32 med_avi_seek_by_time(kal_uint64 time_in_ms)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_int32 need_aud_size;
kal_int32 i;
kal_int32 data_size;
kal_int32 prev_data_size;
kal_int32 data_within;
med_avi_index_struct *idx_p;
kal_int32 ret;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
kal_prompt_trace(MOD_MED, "[MED AVI] med_avi_seek_by_time()");
kal_prompt_trace(MOD_MED, "[MED AVI] seek_time: %d", time_in_ms);
/* VIDEO!! */
/* rate/scale = FPS */
/* rate/(scale*1000) = frame per ms */
/* scale*1000/rate = ms per frame */
/* frame_idx = time_in_ms/((scale*1000)/rate) */
/*
* [example]
*
* rate = 5000
* scale = 1000
* fps = 5
* frame per ms = 5/1000
* ms per frame = 1000/5 = 200ms
*/
if (time_in_ms > med_avi_p->vid_duration)
{
/* seek time exceed total time */
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_PARAM_ERROR");
return MED_RES_PARAM_ERROR;
}
med_avi_p->vid_frame_idx
= time_in_ms / ((med_avi_p->video_stream_header.scale * 1000) / med_avi_p->video_stream_header.rate);
if (med_avi_p->vid_frame_idx >= med_avi_p->vid_total_frame)
{
/* align to last valid index */
med_avi_p->vid_frame_idx = med_avi_p->vid_total_frame - 1;
}
kal_prompt_trace(MOD_MED, "[MED AVI] vid idx: %d", med_avi_p->vid_frame_idx);
/* AUDIO!! */
/* avg_byte_per_ms = avg_byte_per_sec/1000 */
/* need_aud_size = time_in_ms*avg_byte_per_ms = time_in_ms*avg_byte_per_sec/1000 */
if (med_avi_p->is_valid_aud)
{
/* seek from start */
need_aud_size = time_in_ms * med_avi_p->audio_format_header.avg_byte_per_sec / 1000;
prev_data_size = 0;
data_size = 0;
for (i = 0; i < med_avi_p->aud_total_frame; i++)
{
idx_p = (med_avi_index_struct*) & med_avi_p->aud_idx_list_buf_p[i];
data_size += idx_p->chunk_lenght;
if (data_size > need_aud_size)
{
/* data within this segment */
data_within = need_aud_size - prev_data_size;
/* +8 skip xxdb (4 byte), size (4 byte) */
ret = FSAL_Seek(&med_avi_p->aud_fsal_cntx, idx_p->chunk_offset + 8 + data_within);
if (ret != FSAL_OK)
{
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_INVALID_FORMAT");
return MED_RES_INVALID_FORMAT;
}
med_avi_p->aud_remain_len = idx_p->chunk_lenght - data_within;
med_avi_p->aud_frame_idx = i;
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_OK");
return MED_RES_OK;
}
prev_data_size = data_size;
}
/* V > A */
med_avi_p->aud_frame_idx = med_avi_p->aud_total_frame;
med_avi_p->aud_remain_len = 0;
return MED_RES_OK;
}
kal_prompt_trace(
MOD_MED,
"[MED AVI] aud idx: %d, aud remain: %d",
med_avi_p->aud_frame_idx,
med_avi_p->aud_remain_len);
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_OK");
return MED_RES_OK;
}
/*****************************************************************************
* FUNCTION
* med_avi_open_record_file
* DESCRIPTION
*
* PARAMETERS
* rec_data_p [?]
* filename_p [IN]
* RETURNS
*
*****************************************************************************/
kal_int32 med_avi_open_record_file(med_avi_rec_struct *rec_data_p, const kal_wchar *filename_p)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
kal_char *data_filename_p;
kal_char *idx_filename_p;
kal_int32 v_idx_count;
kal_int32 a_idx_count;
kal_int64 max_limit;
kal_int32 max_count;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
kal_prompt_trace(MOD_MED, "[MED AVI] med_avi_open_record_file()");
/* check if rec_data is valid */
ASSERT(rec_data_p->vid_scale != 0);
med_avi_p->data_h = 0;
med_avi_p->idx_h = 0;
med_avi_p->total_av_data_written = 0;
med_avi_p->av_data_offset = 0;
med_avi_p->vid_frame_count = 0;
med_avi_p->aud_len = 0;
memcpy(&med_avi_p->rec_data, rec_data_p, sizeof(med_avi_rec_struct));
/* allocate file name buf */
data_filename_p = (kal_char*) med_alloc_ext_mem(MAX_FILE_NAME_LEN * ENCODE_BYTE);
ASSERT(data_filename_p != 0);
idx_filename_p = (kal_char*) med_alloc_ext_mem(MAX_FILE_NAME_LEN * ENCODE_BYTE);
ASSERT(idx_filename_p != 0);
/* rate/scale = fps */
v_idx_count = med_avi_p->rec_data.vid_rate/med_avi_p->rec_data.vid_scale;
a_idx_count = 3; /* we assume 3 audio frame per sec */
max_count = (v_idx_count > a_idx_count) ? v_idx_count : a_idx_count;
/* we need record limit size, this will be restricted by playback's idx buffer size */
max_limit =
((kal_uint64)MED_AVI_FSAL_IDX_BUF_SIZE) * ((kal_uint64)1000) /
((kal_uint64)(sizeof(med_avi_index_struct) * (max_count)));
/* we hard code record time to 60 min */
med_avi_p->time_limit = MED_AVI_RECORD_TIME_LIMIT*60*1000; /* in ms */
ASSERT(max_limit > med_avi_p->time_limit);
med_avi_p->ms_per_frame
= ((kal_uint64)med_avi_p->rec_data.vid_scale) * \
((kal_uint64)1000) / \
((kal_uint64)med_avi_p->rec_data.vid_rate);
/*
* [AVI File Format] for MJPEG
*
* = Data File ========================
* RIFF.4.AVI .
* LIST.4.hdlr.avih.4.(file header)
* LIST.4.strl.strh.4.(video header)
* .strf.4.(video format)
* LIST.4.strl.strh.4.(audio header)
* .strf.4.(audio format)
* JUNK.4.(junk)
* LIST.4.movi.xxdb.4.(video data)
* xxdc.4.(video data)
* xxwb.4.(audio data)
* = Idx File =========================
* idx1.4.(list data)
* ====================================
*/
/* data file - avi header and data chunk file */
kal_mem_cpy(data_filename_p, filename_p, MAX_FILE_NAME_LEN * ENCODE_BYTE);
med_remove_file_name((kal_wchar*) data_filename_p);
kal_wstrcat((kal_wchar*) data_filename_p, MED_AVI_VISUAL_FILE);
med_avi_p->data_h = FS_Open((kal_wchar*) data_filename_p, /* VID_TEMP_FILE_ATTRIBUTES */ FS_READ_WRITE | FS_CREATE_ALWAYS);
if (med_avi_p->data_h <= 0)
{
med_free_ext_mem((void **)&data_filename_p);
med_free_ext_mem((void **)&idx_filename_p);
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_OPEN_FILE_FAIL");
return MED_RES_OPEN_FILE_FAIL;
}
/* seek to movi chunk */
med_avi_p->av_data_offset = 4 + 4 + 4; /* (RIFF.4.AVI .) */
med_avi_p->av_data_offset += 4 + 4 + 4 + 4 + 4 + sizeof(med_avi_file_header_struct); /* LIST.4.hdlr.avih.4.(file header) */
med_avi_p->av_data_offset += 4 + 4 + 4 + 4 + 4 + sizeof(med_avi_stream_header_struct); /* LIST.4.strl.strh.4.(video header) */
med_avi_p->av_data_offset += 4 + 4 + sizeof(med_avi_video_format_header_struct); /* .strf.4.(video format) */
med_avi_p->av_data_offset += 4 + 4 + 4 + 4 + 4 + sizeof(med_avi_stream_header_struct); /* LIST.4.strl.strh.4.(audio header) */
med_avi_p->av_data_offset += 4 + 4 + sizeof(med_avi_audio_format_header_struct); /* .strf.4.(audio format) */
med_avi_p->av_data_offset += 4 + 4 + 4; /* LIST.4.movi. */
/* extend file - and seek to movi start */
FS_Extend(med_avi_p->data_h, med_avi_p->av_data_offset);
FS_Seek(med_avi_p->data_h, med_avi_p->av_data_offset, FS_FILE_BEGIN);
/* idx file */
kal_mem_cpy(idx_filename_p, filename_p, MAX_FILE_NAME_LEN * ENCODE_BYTE);
med_remove_file_name((kal_wchar*) idx_filename_p);
kal_wstrcat((kal_wchar*) idx_filename_p, MED_AVI_IDX_FILE);
/* Todo */
FS_Delete((kal_wchar*) idx_filename_p);
med_avi_p->idx_h = FS_Open((kal_wchar*) idx_filename_p, /* VID_TEMP_FILE_ATTRIBUTES */ FS_READ_WRITE | FS_CREATE_ALWAYS);
if (med_avi_p->idx_h <= 0)
{
FS_Close(med_avi_p->data_h);
med_free_ext_mem((void **)&data_filename_p);
med_free_ext_mem((void **)&idx_filename_p);
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_OPEN_FILE_FAIL");
return MED_RES_OPEN_FILE_FAIL;
}
med_free_ext_mem((void **)&data_filename_p);
med_free_ext_mem((void **)&idx_filename_p);
/* extend to idx.4 */
FS_Extend(med_avi_p->idx_h, 8);
FS_Seek(med_avi_p->idx_h, 8, FS_FILE_BEGIN);
/* open file ok, allocate buffer for caching */
med_avi_p->data_buf_p[0] = (kal_char*) med_alloc_ext_mem(MED_AVI_WRITE_DATA_BUF_SIZE);
ASSERT(med_avi_p->data_buf_p[0] != 0);
med_avi_p->data_buf_p[1] = (kal_char*) med_alloc_ext_mem(MED_AVI_WRITE_DATA_BUF_SIZE);
ASSERT(med_avi_p->data_buf_p[1] != 0);
med_avi_p->idx_buf_p[0] = (kal_char*) med_alloc_ext_mem(MED_AVI_WRITE_IDX_BUF_SIZE);
ASSERT(med_avi_p->idx_buf_p[0] != 0);
med_avi_p->idx_buf_p[1] = (kal_char*) med_alloc_ext_mem(MED_AVI_WRITE_IDX_BUF_SIZE);
ASSERT(med_avi_p->idx_buf_p[1] != 0);
med_avi_p->act_data_buf_id = 0;
med_avi_p->act_idx_buf_id = 0;
med_avi_p->data_written[0] = 0;
med_avi_p->data_written[1] = 0;
med_avi_p->idx_written[0] = 0;
med_avi_p->idx_written[1] = 0;
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_OK");
return MED_RES_OK;
}
/*****************************************************************************
* FUNCTION
* med_avi_close_record_file
* DESCRIPTION
*
* PARAMETERS
* void
* RETURNS
*
*****************************************************************************/
kal_int32 med_avi_close_record_file(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
kal_prompt_trace(MOD_MED, "[MED AVI] med_avi_close_record_file()");
/* dump remain data in buffer to file */
med_avi_toggle_data_buffer();
med_avi_toggle_idx_buffer();
med_avi_dump_data_buffer_to_file();
med_avi_dump_idx_buffer_to_file();
/* make sure resource is not freed yet */
ASSERT(med_avi_p->data_buf_p[0] != 0);
ASSERT(med_avi_p->data_buf_p[1] != 0);
ASSERT(med_avi_p->idx_buf_p[0] != 0);
ASSERT(med_avi_p->idx_buf_p[1] != 0);
med_free_ext_mem((void **)&med_avi_p->data_buf_p[0]);
med_free_ext_mem((void **)&med_avi_p->data_buf_p[1]);
med_free_ext_mem((void **)&med_avi_p->idx_buf_p[0]);
med_free_ext_mem((void **)&med_avi_p->idx_buf_p[1]);
med_avi_p->data_buf_p[0] = NULL;
med_avi_p->data_buf_p[1] = NULL;
med_avi_p->idx_buf_p[0] = NULL;
med_avi_p->idx_buf_p[1] = NULL;
if (med_avi_p->data_h != 0)
{
FS_Close(med_avi_p->data_h);
}
if (med_avi_p->idx_h != 0)
{
FS_Close(med_avi_p->idx_h);
}
kal_prompt_trace(MOD_MED, "[MED AVI] ret: MED_RES_OK");
return MED_RES_OK;
}
/*****************************************************************************
* FUNCTION
* med_avi_toggle_data_buffer
* DESCRIPTION
*
* PARAMETERS
* void
* RETURNS
* void
*****************************************************************************/
void med_avi_toggle_data_buffer(void)
{
/*----------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -