bool MP4Encoder::Write264Metadata(MP4FileHandle hMp4File,LPMP4ENC_Metadata lpMetadata)
{
    m_videoId = MP4AddH264VideoTrack
        (hMp4File, 
        m_nTimeScale, 
        m_nTimeScale / m_nFrameRate, 
        m_nWidth, // width
        m_nHeight,// height
        lpMetadata->Sps[1], // sps[1] AVCProfileIndication
        lpMetadata->Sps[2], // sps[2] profile_compat
        lpMetadata->Sps[3], // sps[3] AVCLevelIndication
        3);           // 4 bytes length before each NAL unit
    if (m_videoId == MP4_INVALID_TRACK_ID)
    {
        printf("add video track failed.\n");
        return false;
    }
    MP4SetVideoProfileLevel(hMp4File, 0x01); //  Simple Profile @ Level 3

    // write sps
    MP4AddH264SequenceParameterSet(hMp4File,m_videoId,lpMetadata->Sps,lpMetadata->nSpsLen);

    // write pps
    MP4AddH264PictureParameterSet(hMp4File,m_videoId,lpMetadata->Pps,lpMetadata->nPpsLen);

    return true;
}
Example #2
0
static void init_video_track(MP4FileHandle mp4, MP4TrackId *video, switch_frame_t *frame)
{
	int width = 0;
	int height = 0;
	uint8_t *sps_buffer = frame->data;
	uint32_t sps_bytes = frame->datalen;

	sps_buffer++;

	if (frame->img) {
		width = frame->img->d_w;
		height = frame->img->d_h;
	} else {
		parse_sps_video_size(sps_buffer, sps_bytes, &width, &height);
	}

	MP4SetTimeScale(mp4, TIMESCALE);

	*video = MP4AddH264VideoTrack(mp4, TIMESCALE, MP4_INVALID_DURATION, width, height, *(sps_buffer), *(sps_buffer+1), *(sps_buffer+2), SampleLenFieldSize - 1);

	if (*video == MP4_INVALID_TRACK_ID) {
		return;
	}

	MP4AddH264SequenceParameterSet(mp4, *video, --sps_buffer, sps_bytes);

	/*
	MP4SetVideoProfileLevel sets the minumum profile/level of MPEG-4 video support necessary to render the contents of the file.

	ISO/IEC 14496-1:2001 MPEG-4 Systems defines the following values:
	0x00 Reserved
	0x01 Simple Profile @ Level 3
	0x02 Simple Profile @ Level 2
	0x03 Simple Profile @ Level 1
	0x04 Simple Scalable Profile @ Level 2
	0x05 Simple Scalable Profile @ Level 1
	0x06 Core Profile @ Level 2
	0x07 Core Profile @ Level 1
	0x08 Main Profile @ Level 4
	0x09 Main Profile @ Level 3
	0x0A Main Profile @ Level 2
	0x0B N-Bit Profile @ Level 2
	0x0C Hybrid Profile @ Level 2
	0x0D Hybrid Profile @ Level 1
	0x0E Basic Animated Texture @ Level 2
	0x0F Basic Animated Texture @ Level 1
	0x10 Scalable Texture @ Level 3
	0x11 Scalable Texture @ Level 2
	0x12 Scalable Texture @ Level 1
	0x13 Simple Face Animation @ Level 2
	0x14 Simple Face Animation @ Level 1
	0x15-0x7F Reserved
	0x80-0xFD User private
	0xFE No audio profile specified
	0xFF No audio required
	*/
	MP4SetVideoProfileLevel(mp4, 0x7F);
}
Example #3
0
int Mp4Encoder::WriteH264Data(u_char * pData, int size)
{
	int type = pData[4] & 0x1f;

	if (type == 0x07) {			// sps

		// 添加h264 track
		if (m_videoId == MP4_INVALID_TRACK_ID) {
			m_videoId = MP4AddH264VideoTrack(m_hMp4File, m_nVTimeScale, m_nVTimeScale / m_nFrameRate, m_nWidth,	// width
											 m_nHeight,	// height
											 pData[5],	// sps[1] AVCProfileIndication
											 pData[6],	// sps[2] profile_compat
											 pData[7],	// sps[3] AVCLevelIndication
											 3);	// 4 bytes length before each NAL unit
			if (m_videoId == MP4_INVALID_TRACK_ID) {
				printf("add video track failed.\n");
				return 0;
			}

			MP4SetVideoProfileLevel(m_hMp4File, 0x7F);	//  Simple Profile @ Level
		}

		MP4AddH264SequenceParameterSet(m_hMp4File, m_videoId, pData + 4,
									   size - 4);
	} else if (type == 0x08) {	// pps
		MP4AddH264PictureParameterSet(m_hMp4File, m_videoId, pData + 4,
									  size - 4);
	} else {
		// MP4 Nalu前四个字节表示Nalu长度(no 00 00 00 01)
		pData[0] = (size - 4) >> 24;
		pData[1] = (size - 4) >> 16;
		pData[2] = (size - 4) >> 8;
		pData[3] = (size - 4) & 0xff;

		if (!MP4WriteSample
			(m_hMp4File, m_videoId, pData, size, MP4_INVALID_DURATION, 0, 1)) {
			return 0;
		}
	}

	return 0;
}
bool mpeg_video_recorder::InitRecording(int width, int height){
	coid::charstr mp4FileName(m_sVideoFolderPath);
	mp4FileName << "capture_";
	mp4FileName << coid::msec_timer::get_time();
	mp4FileName << ".mp4";
	MP4FileHandle fileHandle = MP4Create(mp4FileName.c_str(), MP4FileMode::FILEMODE_CREATE);
	if (!MP4_IS_VALID_FILE_HANDLE(fileHandle)){
		coid::charstr msg;
		msg << ERRORMESSAGE(" ");
		msg << "Can't create Mp4 file! Path: " << mp4FileName;
		log(msg);
		return false;
	}

	m_IsRecording = true;
	m_hMp4FileHandle = fileHandle;
	m_iVideoTrackID = MP4_INVALID_TRACK_ID;

	coid::bifstream cfgFile(m_sVideoFolderPath+"x264.cfg");
	coid::fmtstreamcxx fmt;
	coid::metastream meta(fmt);

	if (cfgFile.is_open()){
		try{
			fmt.bind(cfgFile);
			meta.stream_in(m_oX264Cfg);
		}
		catch (coid::exception& e){

		}
	}
	else{
		log(WARNINGMESSAGE("x264 configuration file does not exists!"));
		fmt.bind(coid::nullstream);
		meta.xstream_in(m_oX264Cfg);
	}

	meta.stream_acknowledge();
	
	x264_param_t param;
	x264_param_default_preset(&param, m_oX264Cfg.m_sPreset.c_str(), "zerolatency");
	param.i_threads = m_oX264Cfg.m_iThreadCount;
	param.i_width = width;
	param.i_height = height;
	param.i_fps_num = 30;
	param.i_fps_den = 1;
	// Intra refres:
	param.i_keyint_max = 30;
	param.b_intra_refresh = 1;
	//Rate control:
	param.rc.i_rc_method = X264_RC_CRF;
	param.rc.f_rf_constant = 25;
	param.rc.f_rf_constant_max = 35;
	//For streaming:
	param.b_repeat_headers = 1;
	param.b_annexb = 1;
	x264_param_apply_profile(&param, "baseline");

	m_pEncoder = x264_encoder_open(&param);

	MP4TrackId videoTrackID = MP4AddH264VideoTrack(m_hMp4FileHandle, 90000, MP4_INVALID_DURATION, width, height, 0, 1, 0, 3);
	if (!MP4_IS_VALID_TRACK_ID(videoTrackID)){
		MP4Close(m_hMp4FileHandle);
		return false;
	}

	m_iVideoTrackID = videoTrackID;

	m_iWidth = width;
	m_iHeight = height;

	m_pLastNals = NULL;
	m_uiLastTimestampNs = 0;
	m_uiFrameIndex = 0;

	return true;
}
int MP4Encoder::WriteH264Data(MP4FileHandle hMp4File,const unsigned char* pData,int size)
{
    if(hMp4File == NULL)
    {
        return -1;
    }
    if(pData == NULL)
    {
        return -1;
    }
    MP4ENC_NaluUnit nalu;
    int pos = 0, len = 0;
    while (len = ReadOneNaluFromBuf(pData,size,pos,nalu))
    {
        if(nalu.type == 0x07) // sps
        {
            // 添加h264 track    
            m_videoId = MP4AddH264VideoTrack
                (hMp4File, 
                m_nTimeScale, 
                m_nTimeScale / m_nFrameRate, 
                m_nWidth,     // width
                m_nHeight,    // height
                nalu.data[1], // sps[1] AVCProfileIndication
                nalu.data[2], // sps[2] profile_compat
                nalu.data[3], // sps[3] AVCLevelIndication
                3);           // 4 bytes length before each NAL unit
            if (m_videoId == MP4_INVALID_TRACK_ID)
            {
                printf("add video track failed.\n");
                return 0;
            }
            MP4SetVideoProfileLevel(hMp4File, 1); //  Simple Profile @ Level 3

            MP4AddH264SequenceParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);
        }
        else if(nalu.type == 0x08) // pps
        {
            MP4AddH264PictureParameterSet(hMp4File,m_videoId,nalu.data,nalu.size);
        }
        else
        {
            int datalen = nalu.size+4;
            unsigned char *data = new unsigned char[datalen];
            // MP4 Nalu前四个字节表示Nalu长度
            data[0] = nalu.size>>24;
            data[1] = nalu.size>>16;
            data[2] = nalu.size>>8;
            data[3] = nalu.size&0xff;
            memcpy(data+4,nalu.data,nalu.size);
            if(!MP4WriteSample(hMp4File, m_videoId, data, datalen,MP4_INVALID_DURATION, 0, 1))
            {
                return 0;
            }
            delete[] data;
        }

        pos += len;
    }
    return pos;
}