示例#1
0
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;
}
示例#2
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;
}
示例#3
0
static switch_status_t do_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
{
	uint32_t datalen = frame->datalen;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	int is_iframe = 0;
	uint32_t size;
	uint8_t *hdr = NULL;
	uint8_t fragment_type;
	uint8_t nal_type;
	uint8_t start_bit;
	mp4_file_context_t *context = handle->private_info;

	hdr = (uint8_t *)frame->data;
	fragment_type = hdr[0] & 0x1f;
	nal_type = hdr[1] & 0x1f;
	start_bit = hdr[1] & 0x80;
	is_iframe = (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) || fragment_type == 5 || fragment_type ==7 || fragment_type ==8) ? 1 : 0;

	// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x | len:%d m:%d st:%d i:%d\n", hdr[0], hdr[1], hdr[2], datalen, frame->m, start_bit, is_iframe);

	size = htonl(datalen);
	switch_buffer_write(context->buf, &size, 4);
	switch_buffer_write(context->buf, hdr, datalen);

	switch_mutex_lock(context->mutex);

	if (fragment_type == 7 && !context->sps_set) { //sps
		context->sps_set = 1;

		init_video_track(context->fd, &context->video, frame);
		if (context->video == MP4_INVALID_TRACK_ID) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add video track!\n");
			switch_goto_status(SWITCH_STATUS_FALSE, end);
		}
	} else if (fragment_type == 8 && context->sps_set && !context->pps_set) { //pps
		MP4AddH264PictureParameterSet(context->fd, context->video, hdr, datalen);
		context->pps_set = 1;
	}

	if (nal_type == 7 || nal_type == 8 || frame->m == 0) {
	} else if (context->sps_set && context->pps_set) {
		uint32_t used = switch_buffer_inuse(context->buf);
		const void *data;
		int duration = 0;

		if (!context->timer.interval) {
			switch_core_timer_init(&context->timer, "soft", 1, 1, context->pool);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "init timer\n");
		} else {
			switch_core_timer_sync(&context->timer);
		}

		duration = context->timer.samplecount - context->last_pts;

		// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "samplecount: %u, duration: %u\n", context->timer.samplecount, duration);
		switch_buffer_peek_zerocopy(context->buf, &data);

		if (context->last_pts == 0) { // first img, write at the very beginning so we don't see blank screen
			duration /= 2;
			MP4WriteSample(context->fd, context->video, data, used, duration, 0, is_iframe);

			if (duration > context->offset) {
				duration -= context->offset;
			} else {
				duration = 0;
			}
		}

		context->last_pts = context->timer.samplecount;

		// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "samplecount: %u, duration: %u\n", context->timer.samplecount, duration);

		if (duration) {
			MP4WriteSample(context->fd, context->video, data, used, duration, 0, is_iframe);
		}
		switch_buffer_zero(context->buf);
	}

end:
	switch_mutex_unlock(context->mutex);

	return status;
}
示例#4
0
static void record_video_thread(switch_core_session_t *session, void *obj)
{
	struct record_helper *eh = obj;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_status_t status;
	switch_frame_t *read_frame;
	uint bytes;
	MP4FileHandle mp4;
	MP4TrackId video;
	unsigned char buf[40960];
	int len = 0;
	uint8_t iframe = 0;
	uint32_t *size = (uint32_t *)buf;
	uint8_t *hdr = NULL;
	uint8_t fragment_type;
	uint8_t nal_type;
	uint8_t start_bit;
	uint8_t *sps = NULL;
	// uint8_t *pps = NULL;
	int sps_set = 0;
	int pps_set = 0;

	eh->up = 1;
	mp4 = eh->fd;

	/* Tell the channel to request a fresh vid frame */
	switch_core_session_request_video_refresh(session);

	len = 0;
	while (switch_channel_ready(channel) && eh->up) {
		status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);

		if (!SWITCH_READ_ACCEPTABLE(status)) {
			break;
		}

		if (switch_test_flag(read_frame, SFF_CNG)) {
			continue;
		}

		bytes = read_frame->datalen;

		if (bytes > 2000) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "xxxxxxxx buffer overflow\n");
			continue;
		}

		hdr = read_frame->data;
		fragment_type = hdr[0] & 0x1f;
		nal_type = hdr[1] & 0x1f;
		start_bit = hdr[1] & 0x80;
		iframe = (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) || fragment_type == 5 || fragment_type ==7 || fragment_type ==8) ? 1 : 0;

#if 0
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x | len:%d m:%d st:%d i:%d\n", hdr[0], hdr[1], hdr[2], bytes, read_frame->m, start_bit, iframe);
#endif

		// echo back
		switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);

		if (fragment_type == 7 && !sps_set) { //sps
			sps = malloc(bytes);
			memcpy(sps, read_frame->data, bytes);
			sps_set = 1;

			switch_mutex_lock(eh->mutex);

			init_video_track(mp4, &video, read_frame);
			if (video == MP4_INVALID_TRACK_ID) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add video track!\n");
				switch_mutex_unlock(eh->mutex);
				goto end;
			}

			switch_mutex_unlock(eh->mutex);
			continue;
		} else if (fragment_type == 8 && !pps_set) { //pps
			switch_mutex_lock(eh->mutex);
			MP4AddH264PictureParameterSet(mp4, video, read_frame->data, bytes);
			switch_mutex_unlock(eh->mutex);
			pps_set = 1;
			// continue;
		}

		if ((!sps_set) && (!pps_set)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Waiting for SPS/PPS\n");
			// continue;
		}

		len += 4 + read_frame->datalen;

		if (len > 40960) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffer overflow!!!! %d\n", len);
			len = 0;
			size = (uint32_t *)buf;
			continue;
		}

		*size = htonl(read_frame->datalen);
		memcpy(size + 1, read_frame->data, read_frame->datalen);

		size = (uint32_t *)((uint8_t *)size + 4 + read_frame->datalen);

		if (read_frame->m) {
			int duration = 0;

			switch_mutex_lock(eh->mutex);
			if (!eh->timer.interval) {
				switch_core_timer_init(&eh->timer, "soft", 1, 1, switch_core_session_get_pool(session));
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "init timer\n");
			} else {
				switch_core_timer_sync(&eh->timer);
			}
			switch_mutex_unlock(eh->mutex);

			if (eh->last_pts) {
				duration = eh->timer.samplecount - eh->last_pts;
			}
			eh->last_pts = eh->timer.samplecount;

			switch_mutex_lock(eh->mutex);
			MP4WriteSample(mp4, video, buf, len, duration, 0, iframe);
			switch_mutex_unlock(eh->mutex);
			len = 0;
			size = (uint32_t *)buf;
		}

	}

end:
	eh->up = 0;
	return;
}
示例#5
0
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;
}