Files
gb28181/GB28181Device/media/window_capture_mac.cpp
2024-12-15 20:42:32 +08:00

249 lines
5.0 KiB
C++

/***************************************************************************************
*
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
*
* By downloading, copying, installing or using the software you agree to this license.
* If you do not agree to this license, do not download, install,
* copy or use the software.
*
* Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved.
*
* Redistribution and use in binary forms, with or without modification, are permitted.
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*
****************************************************************************************/
#include "sys_inc.h"
#include "window_capture_mac.h"
#include "media_format.h"
#include "lock.h"
/**************************************************************************************/
static void avfWindowCallback(avf_window_data * data, void * userdata)
{
CMWindowCapture *capture = (CMWindowCapture *)userdata;
capture->windowCallBack(data);
}
void * windowCaptureThread(void * argv)
{
CMWindowCapture *capture = (CMWindowCapture *)argv;
capture->captureThread();
return NULL;
}
/**************************************************************************************/
CMWindowCapture::CMWindowCapture() : CWindowCapture()
{
m_pCapture = NULL;
}
CMWindowCapture::~CMWindowCapture()
{
stopCapture();
}
CWindowCapture * CMWindowCapture::getInstance(char * title)
{
CWindowCapture * pCapture = NULL;
InstanceMap::iterator it;
sys_os_mutex_enter(m_pInstMutex);
it = m_InstanceMap.find(title);
if (it == m_InstanceMap.end())
{
pCapture = (CWindowCapture *) new CMWindowCapture;
if (pCapture)
{
pCapture->m_nRefCnt++;
strcpy(pCapture->m_pTitle, title);
m_InstanceMap[title] = pCapture;
}
}
else
{
pCapture = (CWindowCapture *) it->second;
pCapture->m_nRefCnt++;
}
sys_os_mutex_leave(m_pInstMutex);
return pCapture;
}
void CMWindowCapture::listWindow()
{
avf_window_list();
}
BOOL CMWindowCapture::initCapture(int codec, int width, int height, double framerate, int bitrate)
{
CLock lock(m_pMutex);
if (m_bInited)
{
return TRUE;
}
m_pCapture = avf_window_init(m_pTitle, width, height, framerate);
if (NULL == m_pCapture)
{
log_print(HT_LOG_ERR, "%s, avf_window_init failed\r\n", __FUNCTION__);
return FALSE;
}
m_nWidth = avf_window_get_width(m_pCapture);
m_nHeight = avf_window_get_height(m_pCapture);
m_nPixfmt = avf_window_get_pixfmt(m_pCapture);
m_nFramerate = framerate;
m_nBitrate = bitrate;
avf_window_set_callback(m_pCapture, avfWindowCallback, this);
VideoEncoderParam params;
memset(&params, 0, sizeof(params));
params.SrcWidth = m_nWidth;
params.SrcHeight = m_nHeight;
params.SrcPixFmt = (AVPixelFormat) m_nPixfmt;
params.DstCodec = codec;
params.DstWidth = width ? width : m_nWidth;
params.DstHeight = height ? height : m_nHeight;
params.DstFramerate = framerate;
params.DstBitrate = bitrate;
if (m_encoder.init(&params) == FALSE)
{
return FALSE;
}
m_bInited = TRUE;
return TRUE;
}
BOOL CMWindowCapture::startCapture()
{
CLock lock(m_pMutex);
if (m_hCapture)
{
return TRUE;
}
m_bCapture = TRUE;
m_hCapture = sys_os_create_thread((void *)windowCaptureThread, this);
return m_hCapture ? TRUE : FALSE;
}
void CMWindowCapture::stopCapture()
{
m_bCapture = FALSE;
while (m_hCapture)
{
usleep(10*1000);
}
if (m_pCapture)
{
avf_window_uninit(m_pCapture);
m_pCapture = NULL;
}
m_bInited = FALSE;
}
void CMWindowCapture::windowCallBack(avf_window_data * data)
{
int i;
AVFrame frame;
memset(&frame, 0, sizeof(frame));
for (i = 0; i < 4; i++)
{
frame.data[i] = data->data[i];
frame.linesize[i] = data->linesize[i];
}
frame.extended_data = frame.data;
frame.width = data->width;
frame.height = data->height;
frame.format = data->format;
m_encoder.encode(&frame);
}
BOOL CMWindowCapture::capture()
{
if (!m_bInited)
{
return FALSE;
}
BOOL ret = avf_window_read(m_pCapture);
return ret;
}
void CMWindowCapture::captureThread()
{
int64 cur_delay = 0;
int64 pre_delay = 0;
int timeout = 1000000.0 / m_nFramerate;
uint32 cur_time = 0;
uint32 pre_time = 0;
while (m_bCapture)
{
if (capture())
{
cur_time = sys_os_get_ms();
cur_delay = timeout;
if (pre_time > 0)
{
cur_delay += pre_delay - (cur_time - pre_time) * 1000;
if (cur_delay < 1000)
{
cur_delay = 0;
}
}
pre_time = cur_time;
pre_delay = cur_delay;
if (cur_delay > 0)
{
usleep(cur_delay);
}
}
else
{
usleep(10*1000);
}
}
m_hCapture = 0;
}