📄 file_capture_decoder.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2006 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file file_capture_decoder.cpp
*
* $Revision: 1.30 $
*
* File Capture Decoder - provides a sample decoder which captures all decode
* data and writes it to a file.
*
*/
#include <string.h>
#include <time.h>
#include "file_capture_decoder.h"
#include "arch.h"
#include "error.h"
#include "dbgprint.h"
/********************************************************************************
CONSTANTS
********************************************************************************/
#define DBG_FILE_CAPTURE_DECODER DBG_VERBOSE
#define DBG_ON(x) (DBG_FILE_CAPTURE_DECODER >= x)
#define FILE_CAPTURE_DECODER_THREAD_STACK_SIZE 2048
#define FILE_CAPTURE_DECODER_DECODE_DONE_EVENT_TIMEOUT_IN_SECONDS 5
#define FILE_CAPTURE_DECODER_PRESENTATION_START_EVENT_TIMEOUT_IN_SECONDS 2
#define FILE_CAPTURE_DECODER_MPEG_STATUS_THRESHOLD_IN_BYTES 2*1024*1024
#define FILE_CAPTURE_DECODER_PCM_STATUS_THRESHOLD_IN_BYTES 48*1024
#define FILE_CAPTURE_ROOT_DIRECTORY ""
/**
*******************************************************************************
* FileCaptureDecoderThread is the entry point for the thread which pretends to
* decode the captured data by sending presentation start and decode finished
* event notifications after pre-defined timeouts.
*
* @param parameter pointer to the FileCaptureDecoder instance to be monitored
*
* @return VDVD_SUCCESS
*******************************************************************************/
ULONG FileCaptureDecoderThread ( void* parameter )
{
FileCaptureDecoder* decoder = (FileCaptureDecoder*)parameter;
BOOLEAN presentationStarted = FALSE;
uint32 startReceivedDataTime = 0;
uint32 endReceivedDataTime = 0;
uint32 elapsedTime = 0;
presentationStarted = FALSE;
while ( decoder->m_threadExitRequest == FALSE )
{
// Poll to see if we have received any data
if ( decoder->m_receivedDataFlag == TRUE )
{
endReceivedDataTime = (uint32)time(NULL);
decoder->m_receivedDataFlag = FALSE;
if ( startReceivedDataTime == 0 )
{
startReceivedDataTime = endReceivedDataTime;
}
}
// if we have received some data, and have not yet sent presentation
// started notification check for presentation start timeout
if (( startReceivedDataTime > 0 ) && ( presentationStarted == FALSE))
{
elapsedTime = (ULONG)time(NULL) - startReceivedDataTime;
if ( elapsedTime >= FILE_CAPTURE_DECODER_PRESENTATION_START_EVENT_TIMEOUT_IN_SECONDS )
{
presentationStarted = TRUE;
decoder->Notify(DECODE_EVENT_PRESENTATION_START);
}
}
// if we have received some data check for decode finished timeout
if ( endReceivedDataTime > 0 )
{
elapsedTime = (ULONG)time(NULL) - endReceivedDataTime;
if ( elapsedTime >= FILE_CAPTURE_DECODER_DECODE_DONE_EVENT_TIMEOUT_IN_SECONDS )
{
decoder->Notify(DECODE_EVENT_DECODE_DONE);
startReceivedDataTime = 0;
endReceivedDataTime = 0;
presentationStarted = FALSE;
}
}
OS_TaskDelay(OS_WAIT_1S / 10);
}
return ( VDVD_SUCCESS );
}
/**
*******************************************************************************
* FileCaptureDecoder::FileCaptureDecoder initialize members to known state
*
*******************************************************************************/
FileCaptureDecoder::FileCaptureDecoder ( void )
{
m_name = NULL;
m_threadId = (ULONG)OS_FAILURE;
m_threadExitRequest = FALSE;
m_receivedDataFlag = FALSE;
m_statusUpdateThreshold = 0;
m_numberOfBuffersReceived = 0;
m_numberOfBuffersAvailableToRelease = 0;
m_numberOfBytesReceived = 0;
m_numberOfBytesReceviedSinceLastUserNotification = 0;
m_fileHandle = 0;
m_sequenceNumber = 0;
m_video_pts = 0;
m_video_stc = 0;
m_audio_pts = 0;
m_audio_stc = 0;
memset(&m_decoderSettings,0,sizeof(m_decoderSettings));
m_decoderSettings.streamType = DECODER_STREAM_TYPE_UNKNOWN;
}
/**
*******************************************************************************
* FileCaptureDecoder::Create allocate resources needed
*
* @param name decoder name, prefix for output files
*
* @return If the function succeeds, the return value is VDVD_SUCCESS.
*******************************************************************************/
VDVD_ERROR FileCaptureDecoder::Create ( const char* name )
{
AutoMutex autoMutex(&m_mutex);
VDVD_ASSERT_ERROR( (IsReferenced()==TRUE), VDVD_ERROR_OBJECT_HAS_INVALID_STATE );
VDVD_RAISE_ERROR( Decoder::Create( "FileCaptureDecoder" ) );
m_threadId = OS_TaskSpawnParam("FileCaptureDecoderThread",
OS_TASK_NORMAL_PRIORITY,
FILE_CAPTURE_DECODER_THREAD_STACK_SIZE,
FileCaptureDecoderThread,
(void*)this,
NULL);
VDVD_ASSERT_ERROR( (m_threadId==(ULONG)OS_FAILURE), VDVD_ERROR_PLATFORM_FAILED );
m_name = name;
m_threadExitRequest = FALSE;
m_receivedDataFlag = FALSE;
m_statusUpdateThreshold = 0;
m_numberOfBuffersReceived = 0;
m_numberOfBuffersAvailableToRelease = 0;
m_numberOfBytesReceived = 0;
m_numberOfBytesReceviedSinceLastUserNotification = 0;
m_sequenceNumber = 0;
m_video_pts = 0;
m_video_stc = 0;
m_audio_pts = 0;
m_audio_stc = 0;
return ( VDVD_SUCCESS );
}
/**
*******************************************************************************
* FileCaptureDecoder::Create frees resources allocated
*
* @return If the function succeeds, the return value is VDVD_SUCCESS.
*******************************************************************************/
VDVD_ERROR FileCaptureDecoder::Destroy ( void )
{
AutoMutex autoMutex(&m_mutex);
int result;
VDVD_ASSERT_ERROR( (IsReferenced()==FALSE), VDVD_ERROR_OBJECT_HAS_INVALID_STATE );
if ( m_threadId != (ULONG)OS_FAILURE )
{
m_threadExitRequest = TRUE;
OS_TaskJoin(m_threadId);
OS_TaskDelete(m_threadId);
m_threadId = (ULONG)OS_FAILURE;
}
if ( m_fileHandle != 0 )
{
result = FILE_CLOSE(m_fileHandle);
VDVD_ASSERT_ERROR( (result==-1), VDVD_ERROR_PLATFORM_FAILED );
}
VDVD_RAISE_ERROR( Decoder::Destroy() );
return ( VDVD_SUCCESS );
}
/**
*******************************************************************************
* FileCaptureDecoder::CloseOutputFile If currently writing decode data to a file,
* the file is closed. If no data has been written the sequence number is
* re-used for the next file.
*
* @return If the function succeeds, the return value is VDVD_SUCCESS.
*******************************************************************************/
VDVD_ERROR FileCaptureDecoder::CloseOutputFile ( void )
{
int result;
int64 fileLength;
VDVD_ASSERT_ERROR( (IsReferenced()==FALSE), VDVD_ERROR_OBJECT_HAS_INVALID_STATE );
if ( m_fileHandle != 0 )
{
fileLength = FILE_SEEK( m_fileHandle, 0, SEEK_END);
VDVD_ASSERT_ERROR( (fileLength==-1), VDVD_ERROR_PLATFORM_FAILED );
if ( fileLength == 0 )
{
// repeat sequence number if no data was delivered to decoder
m_sequenceNumber--;
}
result = FILE_CLOSE( m_fileHandle );
VDVD_ASSERT_ERROR( (result==-1), VDVD_ERROR_PLATFORM_FAILED );
m_fileHandle = 0;
}
return ( VDVD_SUCCESS );
}
/**
*******************************************************************************
* FileCaptureDecoder::Setup prepares decoder for type of stream
*
* @param settings type of stream to decode
*
* @return If the function succeeds, the return value is VDVD_SUCCESS.
*******************************************************************************/
VDVD_ERROR FileCaptureDecoder::Setup( DECODER_SETTINGS_TYPE* settings )
{
AutoMutex autoMutex(&m_mutex);
char filename[512];
int64 result = 0;
unsigned long int fileLength = 0;
char* extension = NULL;
VDVD_ASSERT_ERROR( (IsReferenced()==FALSE), VDVD_ERROR_OBJECT_HAS_INVALID_STATE );
switch ( settings->streamType )
{
case DECODER_STREAM_TYPE_MPEG2:
extension = "mpeg";
m_statusUpdateThreshold = FILE_CAPTURE_DECODER_MPEG_STATUS_THRESHOLD_IN_BYTES;
break;
case DECODER_STREAM_TYPE_PCM:
extension = "raw";
m_statusUpdateThreshold = FILE_CAPTURE_DECODER_PCM_STATUS_THRESHOLD_IN_BYTES;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -