...
Code Block | ||
---|---|---|
| ||
/* @size Cache size for prerecord to avoid drop frame */ void cm_mp4_record_set_queue_size(gpointer hd, guint size ); /* @duration Record duration in seconds */ void cm_mp4_record_set_duration(gpointer hd, guint64 duration ); /* @duration FFmp4 fragment duration in seconds, default 2s */ void cm_mp4_record_set_fragment_duration(gpointer hd, guint64 duration ); /* @filename MP4 filename, xxxx.mp4 or xxxx%02d.mp4 if seamless enable */ void cm_mp4_record_set_filename(gpointer hd, gchar* filename); /* @thumb Save the 1st video to jpeg as thumbnail if set thumb */ void cm_mp4_record_set_thumbnail(gpointer hd, const char* thumb); /* @en Enable seamless mode */ void cm_mp4_record_set_seamless_mode(gpointer hd, gboolean en); /* @duration The seamless duration in seconds */ void cm_mp4_record_set_seamless_duration(gpointer hd, guint64 duration); void cm_mp4_record_set_bus_handler(gpointer hd, cm_bus_watch_ptr cb, gpointer user_data); /** * Get mp4 record control info. * @key start-pts, stop-pts, current-duration * @val value */ void cm_mp4_record_get_control_info(gpointer hd, gchar* key, gpointer *value); |
It is important to send and wait for EOS before stopping the record, otherwise, the file can not be closed correctly. For mp4 files, this will cause the file to fail to play. For fmp4 files, this will cause the duration to be incorrect.
Code Block |
---|
/* send eos before stop record */ void cm_mp4_record_send_eos(gpointer hd); /* @return get the eos flag after use cm_mp4_record_send_eos */ gboolean cm_mp4_record_is_eos(gpointer hd); |
data
Code Block | ||
---|---|---|
| ||
/** * @vsr A video/x-raw source(cmV4l2Src, ...) or video/h264 source(cmPrerecH264Src) * @asrc An audio/x-raw source(cmAacSrc, ...) or audio/mpeg source(cmPrerecAacSrc) */ void cm_mp4_record_link_to_source(gpointer hd, gpointer vsrc, gpointer asrc); void cm_mp4_record_unlink(gpointer hd); |
...
Code Block | ||
---|---|---|
| ||
//To watch the record status static gboolean _record_bus_handler(GstBus * bus, GstMessage * msg, gpointer user_data){ switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS:{ g_message("mp4 record eos!"); is_exit = TRUE; return GST_BUS_ASYNC; } default: break; } /* pass all messages on the async queue */ return TRUE; } static gboolean _main_loop(gpointer arg) { if(!vsrc) { //Create source vsrc = cm_video_v4l2_source_create("/dev/video0"); //Select video format cm_video_v4l2_source_set_caps_str0(vsrc, "video/x-raw,format=UYVY,width=1280,height=720,colorimetry=(string)1:4:7:1"); cm_video_v4l2_source_start(vsrc); } if(!asrc) { //Create source asrc = cm_audio_alsa_source_create("hw:1,0"); cm_audio_alsa_source_start(asrc); } //Wait the audio source and video source are ready if(cm_audio_alsa_source_is_ready(asrc) && cm_video_v4l2_source_is_ready(vsrc)){ if(!mp4){ mp4 = cm_mp4_record_create(FALSE); cm_mp4_record_set_duration(mp4, 15); time_t cur_time; time(&cur_time); struct tm *local = localtime(&cur_time); char filename[64] = {0}; sprintf(filename, "REC_%04d%02d%02d%02d%02d%02d.mp4", local->tm_year + 1900, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, local->tm_sec); //Set the filename cm_mp4_record_set_filename(mp4, filename); //Link to the source cm_mp4_record_link_to_source(mp4, vsrc, asrc); //Add bus watch cm_mp4_record_set_bus_handler(mp4, _record_bus_handler, NULL); cm_mp4_record_start(mp4); gst_print("%s\n", filename); } else{ if(FALSE == is_exit){ guint64 duration_ms; //Get the current durationduartion mux cm_mp4_record_get_control_info(mp4, "current-duration", (void**)&duration_ms); gst_print("Mp4 recording......%d%%\r", duration_ms / duration / 10); if(duration_ms/1000 >= duration){ is_exit = TRUE; } } } if(is_exit){ if(mp4){ //Send eos before stop cm_mp4_record_send_eos(mp4); //Wait eos is TRUE if(!cm_mp4_record_is_eos(mp4)){ gst_print("\nwait eos...\n"); return TRUE; } //Stop cm_mp4_record_stop(mp4); cm_mp4_record_destroy(mp4); } } } ...... } |
For more details please refer to the demo file.
Test Result
...
The mp4 file can be displayed on the PC.