1286 lines
43 KiB
C++
1286 lines
43 KiB
C++
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
/*
|
|
* vie_file_impl.cc
|
|
*/
|
|
|
|
#include "vie_file_impl.h"
|
|
|
|
// Defines
|
|
#include "vie_defines.h"
|
|
|
|
// Includes
|
|
#include "condition_variable_wrapper.h"
|
|
#include "critical_section_wrapper.h"
|
|
#include "jpeg.h"
|
|
#include "trace.h"
|
|
#include "vie_capturer.h"
|
|
#include "vie_channel.h"
|
|
#include "vie_channel_manager.h"
|
|
#include "vie_encoder.h"
|
|
#include "vie_errors.h"
|
|
#include "vie_file_image.h"
|
|
#include "vie_file_player.h"
|
|
#include "vie_file_recorder.h"
|
|
#include "vie_impl.h"
|
|
#include "vie_input_manager.h"
|
|
#include "vie_render_manager.h"
|
|
|
|
namespace webrtc
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// GetInterface
|
|
// ----------------------------------------------------------------------------
|
|
|
|
ViEFile* ViEFile::GetInterface(VideoEngine* videoEngine)
|
|
{
|
|
#ifdef WEBRTC_VIDEO_ENGINE_FILE_API
|
|
if (videoEngine == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
VideoEngineImpl* vieImpl = reinterpret_cast<VideoEngineImpl*> (videoEngine);
|
|
ViEFileImpl* vieFileImpl = vieImpl;
|
|
(*vieFileImpl)++; // Increase ref count
|
|
|
|
return vieFileImpl;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Release
|
|
//
|
|
// Releases the interface, i.e. reduces the reference counter. The number of
|
|
// remaining references is returned, -1 if released too many times.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::Release()
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, _instanceId,
|
|
"ViEFile::Release()");
|
|
(*this)--; // Decrease ref count
|
|
|
|
WebRtc_Word32 refCount = GetCount();
|
|
if (refCount < 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo, _instanceId,
|
|
"ViEFile release too many times");
|
|
SetLastError(kViEAPIDoesNotExist);
|
|
return -1;
|
|
}
|
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, _instanceId,
|
|
"ViEFile reference count: %d", refCount);
|
|
return refCount;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Constructor
|
|
// ----------------------------------------------------------------------------
|
|
|
|
ViEFileImpl::ViEFileImpl()
|
|
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, _instanceId,
|
|
"ViEFileImpl::ViEFileImpl() Ctor");
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Destructor
|
|
// ----------------------------------------------------------------------------
|
|
|
|
ViEFileImpl::~ViEFileImpl()
|
|
{
|
|
|
|
WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, _instanceId,
|
|
"ViEFileImpl::~ViEFileImpl() Dtor");
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// StartPlayFile
|
|
// ----------------------------------------------------------------------------
|
|
// Play file
|
|
int ViEFileImpl::StartPlayFile(const char* fileNameUTF8, int& fileId,
|
|
const bool loop /*= false*/,
|
|
const webrtc::FileFormats fileFormat
|
|
/*= webrtc::kFileFormatAviFile*/)
|
|
{
|
|
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId), "%s",
|
|
__FUNCTION__);
|
|
|
|
if (!IsInitialized())
|
|
{
|
|
SetLastError(kViENotInitialized);
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s - ViE instance %d not initialized", __FUNCTION__,
|
|
_instanceId);
|
|
return -1;
|
|
}
|
|
|
|
VoiceEngine* voice = _channelManager.GetVoiceEngine();
|
|
const WebRtc_Word32 result = _inputManager.CreateFilePlayer(fileNameUTF8,
|
|
loop,
|
|
fileFormat,
|
|
voice, fileId);
|
|
if (result != 0)
|
|
{
|
|
SetLastError(result);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ViEFileImpl::StopPlayFile(const int fileId)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s(fileId: %d)", __FUNCTION__, fileId);
|
|
|
|
{
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Destroy the capture device
|
|
return _inputManager.DestroyFilePlayer(fileId);
|
|
|
|
}
|
|
|
|
int ViEFileImpl::RegisterObserver(int fileId, ViEFileObserver& observer)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s(fileId: %d)", __FUNCTION__, fileId);
|
|
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
if (ptrViEFilePlayer->IsObserverRegistered())
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, fileId),
|
|
"%s: Observer already registered", __FUNCTION__);
|
|
SetLastError(kViEFileObserverAlreadyRegistered);
|
|
return -1;
|
|
}
|
|
if (ptrViEFilePlayer->RegisterObserver(observer) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, fileId),
|
|
"%s: Failed to register observer", __FUNCTION__, fileId);
|
|
SetLastError(kViEFileUnknownError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int ViEFileImpl::DeregisterObserver(int fileId, ViEFileObserver& observer)
|
|
{
|
|
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s(fileId: %d)", __FUNCTION__, fileId);
|
|
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
if (!ptrViEFilePlayer->IsObserverRegistered())
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, fileId), "%s: No Observer registered",
|
|
__FUNCTION__);
|
|
SetLastError(kViEFileObserverNotRegistered);
|
|
return -1;
|
|
}
|
|
if (ptrViEFilePlayer->DeRegisterObserver() != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, fileId),
|
|
"%s: Failed to deregister observer", __FUNCTION__, fileId);
|
|
SetLastError(kViEFileUnknownError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int ViEFileImpl::SendFileOnChannel(const int fileId, const int videoChannel)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s(fileId: %d)", __FUNCTION__, fileId);
|
|
|
|
ViEChannelManagerScoped cs(_channelManager);
|
|
ViEEncoder* ptrViEEncoder = cs.Encoder(videoChannel);
|
|
if (ptrViEEncoder == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d doesn't exist", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidChannelId);
|
|
return -1;
|
|
}
|
|
|
|
ViEInputManagerScoped is(_inputManager);
|
|
if (is.FrameProvider(ptrViEEncoder) != NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d already connected to a capture device or "
|
|
"file.", __FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileInputAlreadyConnected);
|
|
return -1;
|
|
}
|
|
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
|
|
if (ptrViEFilePlayer->RegisterFrameCallback(videoChannel, ptrViEEncoder)
|
|
!= 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: Failed to register frame callback.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileUnknownError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ViEFileImpl::StopSendFileOnChannel(const int videoChannel)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s(videoChannel: %d)", __FUNCTION__, videoChannel);
|
|
|
|
ViEChannelManagerScoped cs(_channelManager);
|
|
ViEEncoder* ptrViEEncoder = cs.Encoder(videoChannel);
|
|
if (ptrViEEncoder == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d doesn't exist", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidChannelId);
|
|
return -1;
|
|
}
|
|
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViEFrameProviderBase* frameProvider = is.FrameProvider(ptrViEEncoder);
|
|
if (frameProvider == NULL
|
|
|| frameProvider->Id() < kViEFileIdBase
|
|
|| frameProvider->Id() > kViEFileIdMax)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: No file connected to Channel %d", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileNotConnected);
|
|
return -1;
|
|
}
|
|
if (frameProvider->DeregisterFrameCallback(ptrViEEncoder) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Failed to deregister file from channel %d",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileUnknownError);
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int ViEFileImpl::StartPlayFileAsMicrophone(const int fileId,
|
|
const int audioChannel,
|
|
bool mixMicrophone /*= false*/,
|
|
float volumeScaling /*= 1*/)
|
|
{
|
|
ViEInputManagerScoped is(_inputManager);
|
|
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
if (ptrViEFilePlayer->SendAudioOnChannel(audioChannel, mixMicrophone,
|
|
volumeScaling) != 0)
|
|
{
|
|
SetLastError(kViEFileVoEFailure);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int ViEFileImpl::StopPlayFileAsMicrophone(const int fileId,
|
|
const int audioChannel)
|
|
{
|
|
ViEInputManagerScoped is(_inputManager);
|
|
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
|
|
if (ptrViEFilePlayer->StopSendAudioOnChannel(audioChannel) != 0)
|
|
{
|
|
SetLastError(kViEFileVoEFailure);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ViEFileImpl::StartPlayAudioLocally(const int fileId,
|
|
const int audioChannel,
|
|
float volumeScaling /*=1*/)
|
|
{
|
|
ViEInputManagerScoped is(_inputManager);
|
|
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
if (ptrViEFilePlayer->PlayAudioLocally(audioChannel, volumeScaling) != 0)
|
|
{
|
|
SetLastError(kViEFileVoEFailure);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ViEFileImpl::StopPlayAudioLocally(const int fileId, const int audioChannel)
|
|
{
|
|
ViEInputManagerScoped is(_inputManager);
|
|
|
|
ViEFilePlayer* ptrViEFilePlayer = is.FilePlayer(fileId);
|
|
if (ptrViEFilePlayer == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_instanceId),
|
|
"%s: File with id %d is not playing.", __FUNCTION__,
|
|
fileId);
|
|
SetLastError(kViEFileNotPlaying);
|
|
return -1;
|
|
}
|
|
if (ptrViEFilePlayer->StopPlayAudioLocally(audioChannel) != 0)
|
|
{
|
|
SetLastError(kViEFileVoEFailure);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// StartRecordOutgoingVideo
|
|
// ----------------------------------------------------------------------------
|
|
int ViEFileImpl::StartRecordOutgoingVideo(const int videoChannel,
|
|
const char* fileNameUTF8,
|
|
AudioSource audioSource,
|
|
const webrtc::CodecInst& audioCodec,
|
|
const VideoCodec& videoCodec,
|
|
const webrtc::FileFormats fileFormat
|
|
/*= webrtc::kFileFormatAviFile*/)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
ViEChannelManagerScoped cs(_channelManager);
|
|
ViEEncoder* ptrViEEncoder = cs.Encoder(videoChannel);
|
|
if (ptrViEEncoder == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d doesn't exist", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidChannelId);
|
|
return -1;
|
|
}
|
|
ViEFileRecorder& fileRecorder = ptrViEEncoder->GetOutgoingFileRecorder();
|
|
if (fileRecorder.RecordingStarted())
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Already recording outgoing video on channel %d",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileAlreadyRecording);
|
|
return -1;
|
|
}
|
|
|
|
WebRtc_Word32 veChannelId = -1;
|
|
VoiceEngine* vePtr = NULL;
|
|
if (audioSource != NO_AUDIO)
|
|
{
|
|
ViEChannel* ptrViEChannel = cs.Channel(videoChannel);
|
|
veChannelId = ptrViEChannel->VoiceChannel();
|
|
vePtr = _channelManager.GetVoiceEngine();
|
|
|
|
if (!vePtr)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Can't access voice engine. Have SetVoiceEngine "
|
|
"been called?", __FUNCTION__);
|
|
SetLastError(kViEFileVoENotSet);
|
|
return -1;
|
|
}
|
|
}
|
|
if (fileRecorder.StartRecording(fileNameUTF8, videoCodec, audioSource,
|
|
veChannelId, audioCodec, vePtr,
|
|
fileFormat) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Failed to start recording. Check arguments.",
|
|
__FUNCTION__);
|
|
SetLastError(kViEFileUnknownError);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ViEFileImpl::StopRecordOutgoingVideo(const int videoChannel)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
ViEChannelManagerScoped cs(_channelManager);
|
|
ViEEncoder* ptrViEEncoder = cs.Encoder(videoChannel);
|
|
if (ptrViEEncoder == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d doesn't exist", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidChannelId);
|
|
return -1;
|
|
}
|
|
ViEFileRecorder& fileRecorder = ptrViEEncoder->GetOutgoingFileRecorder();
|
|
if (!fileRecorder.RecordingStarted())
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d is not recording.", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileNotRecording);
|
|
return -1;
|
|
}
|
|
if (fileRecorder.StopRecording() != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Failed to stop recording of channel %d.",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileUnknownError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
int ViEFileImpl::StopRecordIncomingVideo(const int videoChannel)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
ViEChannelManagerScoped cs(_channelManager);
|
|
ViEChannel* ptrViEChannel = cs.Channel(videoChannel);
|
|
if (ptrViEChannel == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d doesn't exist", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidChannelId);
|
|
return -1;
|
|
}
|
|
ViEFileRecorder& fileRecorder = ptrViEChannel->GetIncomingFileRecorder();
|
|
if (!fileRecorder.RecordingStarted())
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d is not recording.", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileNotRecording);
|
|
ptrViEChannel->ReleaseIncomingFileRecorder();
|
|
|
|
return -1;
|
|
}
|
|
if (fileRecorder.StopRecording() != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Failed to stop recording of channel %d.",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileUnknownError);
|
|
ptrViEChannel->ReleaseIncomingFileRecorder();
|
|
return -1;
|
|
}
|
|
// Let the channel know we are no longer recording
|
|
ptrViEChannel->ReleaseIncomingFileRecorder();
|
|
return 0;
|
|
|
|
}
|
|
|
|
int ViEFileImpl::StartRecordIncomingVideo(const int videoChannel,
|
|
const char* fileNameUTF8,
|
|
AudioSource audioSource,
|
|
const webrtc::CodecInst& audioCodec,
|
|
const VideoCodec& videoCodec,
|
|
const webrtc::FileFormats fileFormat
|
|
/*= webrtc::kFileFormatAviFile*/)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
ViEChannelManagerScoped cs(_channelManager);
|
|
ViEChannel* ptrViEChannel = cs.Channel(videoChannel);
|
|
if (ptrViEChannel == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Channel %d doesn't exist", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidChannelId);
|
|
return -1;
|
|
}
|
|
ViEFileRecorder& fileRecorder = ptrViEChannel->GetIncomingFileRecorder();
|
|
if (fileRecorder.RecordingStarted())
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Already recording outgoing video on channel %d",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileAlreadyRecording);
|
|
return -1;
|
|
}
|
|
|
|
WebRtc_Word32 veChannelId = -1;
|
|
VoiceEngine* vePtr = NULL;
|
|
if (audioSource != NO_AUDIO)
|
|
{
|
|
veChannelId = ptrViEChannel->VoiceChannel();
|
|
vePtr = _channelManager.GetVoiceEngine();
|
|
|
|
if (!vePtr)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Can't access voice engine. Have SetVoiceEngine "
|
|
"been called?", __FUNCTION__);
|
|
SetLastError(kViEFileVoENotSet);
|
|
return -1;
|
|
}
|
|
}
|
|
if (fileRecorder.StartRecording(fileNameUTF8, videoCodec, audioSource,
|
|
veChannelId, audioCodec, vePtr, fileFormat)
|
|
!= 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s: Failed to start recording. Check arguments.",
|
|
__FUNCTION__);
|
|
SetLastError(kViEFileUnknownError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ============================================================================
|
|
// File information
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// GetFileInformation
|
|
//
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::GetFileInformation(const char* fileName,
|
|
VideoCodec& videoCodec,
|
|
webrtc::CodecInst& audioCodec,
|
|
const webrtc::FileFormats fileFormat
|
|
/*= webrtc::kFileFormatAviFile*/)
|
|
{
|
|
return ViEFilePlayer::GetFileInformation(
|
|
_instanceId, (WebRtc_Word8*) fileName,
|
|
videoCodec, audioCodec, fileFormat);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Snapshot
|
|
// ============================================================================
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::GetRenderSnapshot(const int videoChannel,
|
|
const char* fileNameUTF8)
|
|
{
|
|
// gain access to the renderer for the specified channel and get it's
|
|
// current frame
|
|
ViERenderManagerScoped rs(_renderManager);
|
|
ViERenderer* ptrRender = rs.Renderer(videoChannel);
|
|
if (!ptrRender)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
VideoFrame videoFrame;
|
|
if (-1 == ptrRender->GetLastRenderedFrame(videoChannel, videoFrame))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
const int JPEG_FORMAT = 0;
|
|
int format = JPEG_FORMAT;
|
|
|
|
switch (format)
|
|
{
|
|
case JPEG_FORMAT:
|
|
{
|
|
// *** JPEGEncoder writes the jpeg file for you (no control
|
|
// over it) and does not return you the buffer
|
|
// *** Thusly, we are not going to be writing to the disk here
|
|
|
|
JpegEncoder jpegEncoder;
|
|
|
|
if (-1 == jpegEncoder.SetFileName(fileNameUTF8))
|
|
{
|
|
// could not set filename for whatever reason
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
|
"\tCould not open output file '%s' for writing!",
|
|
fileNameUTF8);
|
|
return -1;
|
|
}
|
|
|
|
if (-1 == jpegEncoder.Encode(videoFrame.Buffer(),
|
|
videoFrame.Length(),
|
|
videoFrame.Width(),
|
|
videoFrame.Height()))
|
|
{
|
|
// could not encode i420->jpeg
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
|
"\tCould not encode i420 -> jpeg file '%s' for "
|
|
"writing!", fileNameUTF8);
|
|
return -1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceFile, _instanceId,
|
|
"\tUnsupported file format for %s", __FUNCTION__);
|
|
return -1;
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// GetRenderSnapshot
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::GetRenderSnapshot(const int videoChannel, ViEPicture& picture)
|
|
{
|
|
|
|
// gain access to the renderer for the specified channel and get it's
|
|
// current frame
|
|
ViERenderManagerScoped rs(_renderManager);
|
|
ViERenderer* ptrRender = rs.Renderer(videoChannel);
|
|
if (!ptrRender)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
VideoFrame videoFrame;
|
|
if (-1 == ptrRender->GetLastRenderedFrame(videoChannel, videoFrame))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// copy from VideoFrame class to ViEPicture struct
|
|
int bufferLength = (int) (videoFrame.Width() * videoFrame.Height() * 1.5);
|
|
picture.data
|
|
= (WebRtc_UWord8*) malloc(bufferLength * sizeof(WebRtc_UWord8));
|
|
memcpy(picture.data, videoFrame.Buffer(), bufferLength);
|
|
picture.size = bufferLength;
|
|
picture.width = videoFrame.Width();
|
|
picture.height = videoFrame.Height();
|
|
picture.type = kVideoI420;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// GetCaptureDeviceSnapshot
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::GetCaptureDeviceSnapshot(const int captureId,
|
|
const char* fileNameUTF8)
|
|
{
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViECapturer* ptrCapture = is.Capture(captureId);
|
|
if (!ptrCapture)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
VideoFrame videoFrame;
|
|
if (GetNextCapturedFrame(captureId, videoFrame) == -1)
|
|
{
|
|
// Failed to get a snapshot...
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
|
"Could not gain acces to capture device %d video frame "
|
|
"%s:%d", captureId, __FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
const int JPEG_FORMAT = 0;
|
|
int format = JPEG_FORMAT;
|
|
|
|
switch (format)
|
|
{
|
|
case JPEG_FORMAT:
|
|
{
|
|
// *** JPEGEncoder writes the jpeg file for you (no control
|
|
// over it) and does not return you the buffer
|
|
// *** Thusly, we are not going to be writing to the disk here
|
|
|
|
JpegEncoder jpegEncoder;
|
|
|
|
if (-1 == jpegEncoder.SetFileName(fileNameUTF8))
|
|
{
|
|
// could not set filename for whatever reason
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
|
"\tCould not open output file '%s' for writing!",
|
|
fileNameUTF8);
|
|
return -1;
|
|
}
|
|
|
|
if (-1 == jpegEncoder.Encode(videoFrame.Buffer(),
|
|
videoFrame.Length(),
|
|
videoFrame.Width(),
|
|
videoFrame.Height()))
|
|
{
|
|
// could not encode i420->jpeg
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
|
"\tCould not encode i420 -> jpeg file '%s' for "
|
|
"writing!", fileNameUTF8);
|
|
return -1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceFile, _instanceId,
|
|
"\tUnsupported file format for %s", __FUNCTION__);
|
|
return -1;
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// GetCaptureDeviceSnapshot
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::GetCaptureDeviceSnapshot(const int captureId,
|
|
ViEPicture& picture)
|
|
{
|
|
VideoFrame videoFrame;
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViECapturer* ptrCapture = is.Capture(captureId);
|
|
if (!ptrCapture)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (GetNextCapturedFrame(captureId, videoFrame) == -1)
|
|
{
|
|
// Failed to get a snapshot...
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, _instanceId,
|
|
"Could not gain acces to capture device %d video frame "
|
|
"%s:%d", captureId, __FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
// copy from VideoFrame class to ViEPicture struct
|
|
int bufferLength = (int) (videoFrame.Width() * videoFrame.Height() * 1.5);
|
|
picture.data
|
|
= (WebRtc_UWord8*) malloc(bufferLength * sizeof(WebRtc_UWord8));
|
|
memcpy(picture.data, videoFrame.Buffer(), bufferLength);
|
|
picture.size = bufferLength;
|
|
picture.width = videoFrame.Width();
|
|
picture.height = videoFrame.Height();
|
|
picture.type = kVideoI420;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// FreePicture
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::FreePicture(ViEPicture& picture)
|
|
{
|
|
if (picture.data)
|
|
free(picture.data);
|
|
|
|
picture.data = NULL;
|
|
picture.size = 0;
|
|
picture.width = 0;
|
|
picture.height = 0;
|
|
picture.type = kVideoUnknown;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Capture device images
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// SetCaptureDeviceImage
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::SetCaptureDeviceImage(const int captureId,
|
|
const char* fileNameUTF8)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, _instanceId,
|
|
"%s(captureId: %d)", __FUNCTION__, captureId);
|
|
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViECapturer* ptrCapture = is.Capture(captureId);
|
|
if (!ptrCapture)
|
|
{
|
|
SetLastError(kViEFileInvalidCaptureId);
|
|
return -1;
|
|
}
|
|
|
|
VideoFrame captureImage;
|
|
if (ViEFileImage::ConvertJPEGToVideoFrame(
|
|
ViEId(_instanceId, captureId), fileNameUTF8, captureImage) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, captureId),
|
|
"%s(captureId: %d) Failed to open file.", __FUNCTION__,
|
|
captureId);
|
|
SetLastError(kViEFileInvalidFile);
|
|
return -1;
|
|
}
|
|
if (ptrCapture->SetCaptureDeviceImage(captureImage))
|
|
{
|
|
SetLastError(kViEFileSetCaptureImageError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// SetCaptureDeviceImage
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::SetCaptureDeviceImage(const int captureId,
|
|
const ViEPicture& picture)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, _instanceId,
|
|
"%s(captureId: %d)", __FUNCTION__, captureId);
|
|
|
|
if (picture.type != kVideoI420)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, captureId),
|
|
"%s(captureId: %d) Not a valid picture type.",
|
|
__FUNCTION__, captureId);
|
|
SetLastError(kViEFileInvalidArgument);
|
|
return -1;
|
|
}
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViECapturer* ptrCapture = is.Capture(captureId);
|
|
if (!ptrCapture)
|
|
{
|
|
SetLastError(kViEFileSetCaptureImageError);
|
|
return -1;
|
|
}
|
|
|
|
VideoFrame captureImage;
|
|
if (ViEFileImage::ConvertPictureToVideoFrame(
|
|
ViEId(_instanceId,captureId), picture, captureImage) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, captureId),
|
|
"%s(captureId: %d) Failed to use picture.", __FUNCTION__,
|
|
captureId);
|
|
SetLastError(kViEFileInvalidFile);
|
|
return -1;
|
|
}
|
|
if (ptrCapture->SetCaptureDeviceImage(captureImage))
|
|
{
|
|
SetLastError(kViEFileInvalidCapture);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Render images
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// SetRenderStartImage
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::SetRenderStartImage(const int videoChannel,
|
|
const char* fileNameUTF8)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s(videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
ViERenderManagerScoped rs(_renderManager);
|
|
ViERenderer* ptrRender = rs.Renderer(videoChannel);
|
|
if (!ptrRender)
|
|
{
|
|
SetLastError(kViEFileInvalidRenderId);
|
|
return -1;
|
|
}
|
|
|
|
VideoFrame startImage;
|
|
if (ViEFileImage::ConvertJPEGToVideoFrame(
|
|
ViEId(_instanceId, videoChannel), fileNameUTF8, startImage) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Failed to open file.", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidFile);
|
|
return -1;
|
|
}
|
|
if (ptrRender->SetRenderStartImage(startImage) != 0)
|
|
{
|
|
SetLastError(kViEFileSetStartImageError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// SetRenderStartImage
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::SetRenderStartImage(const int videoChannel,
|
|
const ViEPicture& picture)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s(videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
if (picture.type != kVideoI420)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Not a valid picture type.",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileInvalidArgument);
|
|
return -1;
|
|
}
|
|
|
|
ViERenderManagerScoped rs(_renderManager);
|
|
ViERenderer* ptrRender = rs.Renderer(videoChannel);
|
|
if (!ptrRender)
|
|
{
|
|
SetLastError(kViEFileInvalidRenderId);
|
|
return -1;
|
|
}
|
|
|
|
VideoFrame startImage;
|
|
if (ViEFileImage::ConvertPictureToVideoFrame(
|
|
ViEId(_instanceId, videoChannel), picture, startImage) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Failed to use picture.",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileInvalidCapture);
|
|
return -1;
|
|
}
|
|
if (ptrRender->SetRenderStartImage(startImage) != 0)
|
|
{
|
|
SetLastError(kViEFileSetStartImageError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Timeout image
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
//
|
|
// SetRenderTimeoutImage
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int ViEFileImpl::SetRenderTimeoutImage(const int videoChannel,
|
|
const char* fileNameUTF8,
|
|
const unsigned int timeoutMs)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s(videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
ViERenderManagerScoped rs(_renderManager);
|
|
ViERenderer* ptrRender = rs.Renderer(videoChannel);
|
|
if (!ptrRender)
|
|
{
|
|
SetLastError(kViEFileInvalidRenderId);
|
|
return -1;
|
|
}
|
|
VideoFrame timeoutImage;
|
|
if (ViEFileImage::ConvertJPEGToVideoFrame(
|
|
ViEId(_instanceId,videoChannel), fileNameUTF8, timeoutImage) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Failed to open file.", __FUNCTION__,
|
|
videoChannel);
|
|
SetLastError(kViEFileInvalidFile);
|
|
return -1;
|
|
}
|
|
WebRtc_Word32 timeoutTime = timeoutMs;
|
|
if (timeoutMs < kViEMinRenderTimeoutTimeMs)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Invalid timeoutMs, using %d.",
|
|
__FUNCTION__, videoChannel, kViEMinRenderTimeoutTimeMs);
|
|
timeoutTime = kViEMinRenderTimeoutTimeMs;
|
|
}
|
|
if (timeoutMs > kViEMaxRenderTimeoutTimeMs)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Invalid timeoutMs, using %d.",
|
|
__FUNCTION__, videoChannel, kViEMaxRenderTimeoutTimeMs);
|
|
timeoutTime = kViEMaxRenderTimeoutTimeMs;
|
|
}
|
|
if (ptrRender->SetTimeoutImage(timeoutImage, timeoutTime) != 0)
|
|
{
|
|
SetLastError(kViEFileSetRenderTimeoutError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int ViEFileImpl::SetRenderTimeoutImage(const int videoChannel,
|
|
const ViEPicture& picture,
|
|
const unsigned int timeoutMs)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel), "%s(videoChannel: %d)",
|
|
__FUNCTION__, videoChannel);
|
|
|
|
if (picture.type != kVideoI420)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Not a valid picture type.",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileInvalidArgument);
|
|
return -1;
|
|
}
|
|
|
|
ViERenderManagerScoped rs(_renderManager);
|
|
ViERenderer* ptrRender = rs.Renderer(videoChannel);
|
|
if (!ptrRender)
|
|
{
|
|
SetLastError(kViEFileSetRenderTimeoutError);
|
|
return -1;
|
|
}
|
|
VideoFrame timeoutImage;
|
|
if (ViEFileImage::ConvertPictureToVideoFrame(
|
|
ViEId(_instanceId, videoChannel), picture, timeoutImage) != 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Failed to use picture.",
|
|
__FUNCTION__, videoChannel);
|
|
SetLastError(kViEFileInvalidCapture);
|
|
return -1;
|
|
}
|
|
WebRtc_Word32 timeoutTime = timeoutMs;
|
|
if (timeoutMs < kViEMinRenderTimeoutTimeMs)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Invalid timeoutMs, using %d.",
|
|
__FUNCTION__, videoChannel, kViEMinRenderTimeoutTimeMs);
|
|
timeoutTime = kViEMinRenderTimeoutTimeMs;
|
|
}
|
|
if (timeoutMs > kViEMaxRenderTimeoutTimeMs)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
|
|
ViEId(_instanceId, videoChannel),
|
|
"%s(videoChannel: %d) Invalid timeoutMs, using %d.",
|
|
__FUNCTION__, videoChannel, kViEMaxRenderTimeoutTimeMs);
|
|
timeoutTime = kViEMaxRenderTimeoutTimeMs;
|
|
}
|
|
if (ptrRender->SetTimeoutImage(timeoutImage, timeoutTime) != 0)
|
|
{
|
|
SetLastError(kViEFileSetRenderTimeoutError);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
WebRtc_Word32 ViEFileImpl::GetNextCapturedFrame(WebRtc_Word32 captureId,
|
|
VideoFrame& videoFrame)
|
|
{
|
|
ViEInputManagerScoped is(_inputManager);
|
|
ViECapturer* ptrCapture = is.Capture(captureId);
|
|
if (!ptrCapture)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
ViECaptureSnapshot* snapShot = new ViECaptureSnapshot();
|
|
ptrCapture->RegisterFrameCallback(-1, snapShot);
|
|
bool snapshotTaken =
|
|
snapShot->GetSnapshot(videoFrame, kViECaptureMaxSnapshotWaitTimeMs);
|
|
|
|
// Check once again if it has been destroyed...
|
|
ptrCapture->DeregisterFrameCallback(snapShot);
|
|
delete snapShot;
|
|
snapShot = NULL;
|
|
|
|
if (snapshotTaken)
|
|
{
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
ViECaptureSnapshot::ViECaptureSnapshot() :
|
|
_crit(*CriticalSectionWrapper::CreateCriticalSection()),
|
|
_conditionVaraible(*ConditionVariableWrapper::CreateConditionVariable()),
|
|
_ptrVideoFrame(NULL)
|
|
{
|
|
}
|
|
|
|
ViECaptureSnapshot::~ViECaptureSnapshot()
|
|
{
|
|
_crit.Enter();
|
|
_crit.Leave();
|
|
delete &_crit;
|
|
if (_ptrVideoFrame)
|
|
{
|
|
delete _ptrVideoFrame;
|
|
_ptrVideoFrame = NULL;
|
|
}
|
|
}
|
|
|
|
bool ViECaptureSnapshot::GetSnapshot(VideoFrame& videoFrame,
|
|
unsigned int maxWaitTime)
|
|
{
|
|
_crit.Enter();
|
|
_ptrVideoFrame = new VideoFrame();
|
|
if (_conditionVaraible.SleepCS(_crit, maxWaitTime))
|
|
{
|
|
// Snapshot taken
|
|
videoFrame.SwapFrame(*_ptrVideoFrame);
|
|
delete _ptrVideoFrame;
|
|
_ptrVideoFrame = NULL;
|
|
_crit.Leave();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ViECaptureSnapshot::DeliverFrame(int id, VideoFrame& videoFrame,
|
|
int numCSRCs,
|
|
const WebRtc_UWord32 CSRC[kRtpCsrcSize])
|
|
{
|
|
CriticalSectionScoped cs(_crit);
|
|
if (!_ptrVideoFrame)
|
|
{
|
|
return;
|
|
}
|
|
_ptrVideoFrame->SwapFrame(videoFrame);
|
|
_conditionVaraible.WakeAll();
|
|
return;
|
|
}
|
|
} // namespace webrtc
|