Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Current »

The cmMp4Record is used to mux h264 and AAC to mp4 files. The following features are currently supported:

  • One video/x-raw input or one video/h264 input with prerecord.

  • One video/x-raw and one audio/x-raw input or one video/h264 and one audio/mpeg input with prerecord.

  • Duration control.

  • Seamless support, the user can set the seamless duration.

  • If the video input is video/x-raw, it supports saving the 1st YUV to jpeg as a thumbnail file.


API Instructions

create/destroy

If the input is prerecording data, the data will be processed as h264 and AAC. Otherwise, the input data will be processed as raw data and the record will encode them to h264 or AAC.

/* @prerec Input is prerec data */
gpointer cm_mp4_record_create(gboolean prerec);
void cm_mp4_record_destroy(gpointer hd);

start/stop

void cm_mp4_record_start(gpointer hd);
void cm_mp4_record_stop(gpointer hd);

parameters

/* @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.

/* 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

/**
 * @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);

others

GstElement* cm_mp4_record_get_bin(gpointer hd);

Demo

Mp4 Record Demo

Streaming Structure

Mux video/x-raw and audio/x-raw to mp4 file.

image-20240520-072801.png

Main codes

//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 duartion 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

image-20240520-072831.png

The mp4 file can be displayed on the PC.

  • No labels