⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_v4l_source.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved. *  * Contributor(s):  *		Dave Mackie		dmackie@cisco.com *		Bill May 		wmay@cisco.com */#include "mp4live.h"#include <sys/mman.h>#include "video_v4l_source.h"#include "video_util_rgb.h"//#define DEBUG_TIMESTAMPS 1int CV4LVideoSource::ThreadMain(void) {	while (true) {		int rc;		if (m_source) {			rc = SDL_SemTryWait(m_myMsgQueueSemaphore);		} else {			rc = SDL_SemWait(m_myMsgQueueSemaphore);		}		// semaphore error		if (rc == -1) {			break;		} 		// message pending		if (rc == 0) {			CMsg* pMsg = m_myMsgQueue.get_message();					if (pMsg != NULL) {				switch (pMsg->get_value()) {				case MSG_NODE_STOP_THREAD:					DoStopCapture();	// ensure things get cleaned up					delete pMsg;					return 0;				case MSG_NODE_START:				case MSG_SOURCE_START_VIDEO:					DoStartCapture();					break;				case MSG_NODE_STOP:					DoStopCapture();					break;				case MSG_SOURCE_KEY_FRAME:					DoGenerateKeyFrame();					break;				}				delete pMsg;			}		}		if (m_source) {			try {				ProcessVideo();			}			catch (...) {				DoStopCapture();				break;			}		}	}	return -1;}void CV4LVideoSource::DoStartCapture(void){	if (m_source) {		return;	}	if (!Init()) {		return;	}	m_source = true;}void CV4LVideoSource::DoStopCapture(void){	if (!m_source) {		return;	}	DoStopVideo();	ReleaseDevice();	m_source = false;}bool CV4LVideoSource::Init(void){	if (!InitDevice()) {		return false;	}	m_pConfig->CalculateVideoFrameSize();	InitVideo(		(m_pConfig->m_videoNeedRgbToYuv ?			RGBVIDEOFRAME :			YUVVIDEOFRAME),		true);	SetVideoSrcSize(		m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_WIDTH),		m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_HEIGHT),		m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_WIDTH),		true);	m_maxPasses = (u_int8_t)(m_videoSrcFrameRate + 0.5);	return true;}bool CV4LVideoSource::InitDevice(void){	int rc;	char* deviceName = m_pConfig->GetStringValue(CONFIG_VIDEO_SOURCE_NAME);	u_int16_t format;	// open the video device	m_videoDevice = open(deviceName, O_RDWR);	if (m_videoDevice < 0) {		error_message("Failed to open %s: %s", 			deviceName, strerror(errno));		return false;	}	// get device capabilities	struct video_capability videoCapability;	rc = ioctl(m_videoDevice, VIDIOCGCAP, &videoCapability);	if (rc < 0) {		error_message("Failed to get video capabilities for %s",			deviceName);		goto failure;	}	if (!(videoCapability.type & VID_TYPE_CAPTURE)) {		error_message("Device %s is not capable of video capture!",			deviceName);		goto failure;	}	// N.B. "channel" here is really an input source	struct video_channel videoChannel;	videoChannel.channel = m_pConfig->GetIntegerValue(CONFIG_VIDEO_INPUT);	rc = ioctl(m_videoDevice, VIDIOCGCHAN, &videoChannel);	if (rc < 0) {		error_message("Failed to get video channel info for %s",			deviceName);		goto failure;	}	// select video input and signal type	videoChannel.norm = m_pConfig->GetIntegerValue(CONFIG_VIDEO_SIGNAL);	rc = ioctl(m_videoDevice, VIDIOCSCHAN, &videoChannel);	if (rc < 0) {		error_message("Failed to set video channel info for %s",			deviceName);		goto failure;	}	if (m_pConfig->GetIntegerValue(CONFIG_VIDEO_SIGNAL) == VIDEO_MODE_NTSC) {		m_videoSrcFrameRate = VIDEO_NTSC_FRAME_RATE;	} else {		m_videoSrcFrameRate = VIDEO_PAL_FRAME_RATE;	}	// input source has a TV tuner	if (videoChannel.flags & VIDEO_VC_TUNER) {		struct video_tuner videoTuner;		// get tuner info		if ((int32_t)m_pConfig->GetIntegerValue(CONFIG_VIDEO_TUNER) == -1) {			m_pConfig->SetIntegerValue(CONFIG_VIDEO_TUNER, 0);		}		videoTuner.tuner = m_pConfig->GetIntegerValue(CONFIG_VIDEO_TUNER);		rc = ioctl(m_videoDevice, VIDIOCGTUNER, &videoTuner);		if (rc < 0) {			error_message("Failed to get video tuner info for %s",				deviceName);		}				// set tuner and signal type		videoTuner.mode = m_pConfig->GetIntegerValue(CONFIG_VIDEO_SIGNAL);		rc = ioctl(m_videoDevice, VIDIOCSTUNER, &videoTuner);		if (rc < 0) {			error_message("Failed to set video tuner info for %s",				deviceName);		}		// tune in the desired frequency (channel)		struct CHANLISTS* pChannelList = chanlists;		struct CHANLIST* pChannel = pChannelList[			m_pConfig->GetIntegerValue(CONFIG_VIDEO_CHANNEL_LIST_INDEX)].list;		unsigned long videoFrequencyKHz = pChannel[			m_pConfig->GetIntegerValue(CONFIG_VIDEO_CHANNEL_INDEX)].freq;		unsigned long videoFrequencyTuner =			((videoFrequencyKHz / 1000) << 4) 			| ((videoFrequencyKHz % 1000) >> 6);		rc = ioctl(m_videoDevice, VIDIOCSFREQ, &videoFrequencyTuner);		if (rc < 0) {			error_message("Failed to set video tuner frequency for %s",				deviceName);		}	}	// get info on video capture buffers 	rc = ioctl(m_videoDevice, VIDIOCGMBUF, &m_videoMbuf);	if (rc < 0) {		error_message("Failed to get video capture info for %s", 			deviceName);		goto failure;	}	// map the video capture buffers	m_videoMap = mmap(0, m_videoMbuf.size, 		PROT_READ | PROT_WRITE, MAP_SHARED, m_videoDevice, 0);	if (m_videoMap == MAP_FAILED) {		error_message("Failed to map video capture memory for %s", 			deviceName);		goto failure;	}	// allocate enough frame maps	m_videoFrameMap = (struct video_mmap*)		malloc(m_videoMbuf.frames * sizeof(struct video_mmap));	if (m_videoFrameMap == NULL) {		error_message("Failed to allocate enough memory"); 		goto failure;	}	m_videoFrameMapFrame = (uint64_t *)malloc(m_videoMbuf.frames * sizeof(uint64_t));	m_videoFrameMapTimestamp = (uint64_t *)malloc(m_videoMbuf.frames * sizeof(Timestamp));	m_captureHead = 0;	m_encodeHead = -1;	format = VIDEO_PALETTE_YUV420P;	m_videoFrames = 0;       m_videoSrcFrameDuration = 		(Duration)(((float)TimestampTicks / m_videoSrcFrameRate) + 0.5);       m_cacheTimestamp = true;       if (m_pConfig->GetBoolValue(CONFIG_V4L_CACHE_TIMESTAMP) == false) {	 m_videoMbuf.frames = 2;	 m_cacheTimestamp = false;       }	for (int i = 0; i < m_videoMbuf.frames; i++) {		// initialize frame map		m_videoFrameMap[i].frame = i;		m_videoFrameMap[i].width = 			m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_WIDTH);		m_videoFrameMap[i].height = 			m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_HEIGHT);		m_videoFrameMap[i].format = format;		// give frame to the video capture device		rc = ioctl(m_videoDevice, VIDIOCMCAPTURE, &m_videoFrameMap[i]);		if (rc < 0) {			// try RGB24 palette instead			if (i == 0 && format == VIDEO_PALETTE_YUV420P) {				format = VIDEO_PALETTE_RGB24;				i--;				continue;			} 			error_message("Failed to allocate video capture buffer for %s", 				deviceName);			goto failure;		}		if (i == 0) {		  m_videoCaptureStartTimestamp = GetTimestamp();		}		m_lastVideoFrameMapFrameLoaded = m_videoFrameMapFrame[i] = i;		m_lastVideoFrameMapTimestampLoaded = 		  m_videoFrameMapTimestamp[i] = 		  CalculateVideoTimestampFromFrames(i);	}	if (format == VIDEO_PALETTE_RGB24) {		m_pConfig->m_videoNeedRgbToYuv = true;	}	SetPictureControls();	if (videoCapability.audios) {		SetVideoAudioMute(false);	}	return true;failure:	free(m_videoFrameMap);	if (m_videoMap) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -