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

📄 video_v4l_source.cpp

📁 完整的RTP RTSP代码库
💻 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"#ifndef HAVE_LINUX_VIDEODEV2_H#include <sys/mman.h>#include "video_v4l_source.h"#include "video_util_rgb.h"#include "video_util_filter.h"const char *get_linux_video_type (void){  return "V4L";}//#define DEBUG_TIMESTAMPS 1int CV4LVideoSource::ThreadMain(void) {  m_v4l_mutex = SDL_CreateMutex();	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:					DoStartCapture();					break;				case MSG_NODE_STOP:					DoStopCapture();					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;	}	ReleaseDevice();	m_source = false;	SDL_DestroyMutex(m_v4l_mutex);}bool CV4LVideoSource::Init(void){	m_pConfig->CalculateVideoFrameSize();	InitVideo(true);	SetVideoSrcSize(		m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_WIDTH),		m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_HEIGHT),		m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_WIDTH));	if (!InitDevice()) {		return false;	}	m_maxPasses = (u_int8_t)(m_videoSrcFrameRate + 0.5);	return true;}bool CV4LVideoSource::InitDevice(void){	int rc;	const 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        switch(m_pConfig->GetIntegerValue(CONFIG_VIDEO_SIGNAL)) {        case VIDEO_SIGNAL_PAL:          videoChannel.norm = VIDEO_MODE_PAL;          break;        case VIDEO_SIGNAL_NTSC:          videoChannel.norm = VIDEO_MODE_NTSC;          break;        case VIDEO_SIGNAL_SECAM:          videoChannel.norm = VIDEO_MODE_SECAM;          break;        }        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_SIGNAL_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;       }       uint32_t width, height;       width = m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_WIDTH);       height = m_pConfig->GetIntegerValue(CONFIG_VIDEO_RAW_HEIGHT);              if (strncasecmp(m_pConfig->GetStringValue(CONFIG_VIDEO_FILTER),		       VIDEO_FILTER_DECIMATE,		       strlen(VIDEO_FILTER_DECIMATE)) == 0) {	 uint32_t max_width, max_height;	 switch (m_pConfig->GetIntegerValue(CONFIG_VIDEO_SIGNAL)) {	 case VIDEO_SIGNAL_NTSC:	   max_width = 720;	   max_height = 480;	   break;	 case VIDEO_SIGNAL_PAL:	 case VIDEO_SIGNAL_SECAM:	 default:	   max_width = 768;	   max_height = 576;	   break;	 }	 if (max_width < width * 2 || max_height < height * 2) {	   error_message("Decimate filter choosen with too large video size - max %ux%u",			 max_width / 2, max_height / 2);	 } else {	   m_decimate_filter = true;	   width *= 2;	   height *= 2;	 }       }	for (int i = 0; i < m_videoMbuf.frames; i++) {		// initialize frame map		m_videoFrameMap[i].frame = i;		m_videoFrameMap[i].width = width;		m_videoFrameMap[i].height = 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 - frame %d max %d rc %d errno %d format %d", 				deviceName,				      i, m_videoMbuf.frames, 				      rc, errno, format);			goto failure;		}		if (i == 0) {		  m_videoCaptureStartTimestamp = GetTimestamp();		}		m_lastVideoFrameMapFrameLoaded = m_videoFrameMapFrame[i] = i;		m_lastVideoFrameMapTimestampLoaded = 		  m_videoFrameMapTimestamp[i] = 		  CalculateVideoTimestampFromFrames(i);	}	m_videoNeedRgbToYuv = (format == VIDEO_PALETTE_RGB24);	SetPictureControls();	if (videoCapability.audios) {		SetVideoAudioMute(false);	}	return true;failure:	free(m_videoFrameMap);	if (m_videoMap) {		munmap(m_videoMap, m_videoMbuf.size);		m_videoMap = NULL;	}	close(m_videoDevice);	m_videoDevice = -1;	return false;}void CV4LVideoSource::ReleaseDevice(){	SetVideoAudioMute(true);	// release device resources	munmap(m_videoMap, m_videoMbuf.size);	m_videoMap = NULL;	close(m_videoDevice);	m_videoDevice = -1;}	void CV4LVideoSource::SetVideoAudioMute(bool mute){  if (!m_pConfig->m_videoCapabilities) return;  CVideoCapabilities *vc = (CVideoCapabilities *)m_pConfig->m_videoCapabilities;  if ( !vc->m_hasAudio) {    return;  }	int rc;	struct video_audio videoAudio;

⌨️ 快捷键说明

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