[prev in list] [next in list] [prev in thread] [next in thread]
List: helix-datatype-cvs
Subject: [Datatype-cvs] tools/dtdriver/decoder/audio adepacker.cpp, NONE, 1.1.2.1
From: yuxinliu () helixcommunity ! org
Date: 2012-07-20 9:33:30
[Download RAW message or body]
Update of /cvsroot/datatype/tools/dtdriver/decoder/audio
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv17648
Added Files:
Tag: PRODUCER_14_0_RN
adepacker.cpp
Log Message:
Synopsis
========
This CR implement Pass through feature for producer.
Branch : PRODUCER_14_0_RN
Suggested by Sujeet
Description:
==========
The most of IP camera support H.264 video encoding from the camera. In this case, HMP \
doesn't need to transcode it again. It saves system resource and content quality. \
If RTSP stream source has H.264/AAC codec, HMP pass through encoded data.
This CR support pass through all input stream at the same time. This CR never support \
pass through one stream and encoder another stream.
My solution:
1 Add two option in input: "PassThroughVideo" and "PassThroughAudio", their default \
value are false. Customer can set PassThroughVideo=true and PassThroughAudio=true to \
enable pass through. If the input video stream is h.264 and audio stream is AAC, and \
the PassThroughVideo and PassThroughAudio are true, HMP will pass through the input \
stream.
2 If pass through is enable, HMP will create a pass through pipeline, like the \
following:
Input filter(Dtdriver-> depacketizer->dtdrreader) ==>packetizer filter==> packetizer \
asm mux filter ==> destination filter(rbs)
Input filter(Dtdriver-> depacketizer->dtdrreader) ==>unpacketizer asm mux filter ==> \
destination filter(file write)
3 Implement audio depacketizer and video depacketizer plug-in so that Dtdriver \
plug-in can depacketizer H264 and AAC stream. 264depacketizer.rar and \
aacdepacketizer.rar are source code of the new depacketizer plug-in. Path of the two \
plug-in are: datatype\mp4\audio\aacdepacketizer.
datatype\mp4\video\264depacketizer.
4 Implement new class CAudioSourceDepacketizer in source file adepacker.cpp and \
adepacker.h. Dtdriver plug-in will through class CAudioSourceDepacketizer to search \
audio depacketizer plug-in, and depacketize input stream.
5 I add a new macro HELIX_FEATURE_PASS_THROUGH into source file h264pyld.cpp and \
mp4apyld.cpp so that Passthrough feature can share source file with other feature. I \
define macro HELIX_FEATURE_PASS_THROUGH at Umakefil of 264depacketizer folder and \
aacdepacketizer folder.
Files affected:
=========
datatype/mp4/payload/h264pyld.cpp
datatype/mp4/payload/mp4apyld.cpp
client_rn/encodesvc/plugins/input/dtdrreader/hxdtdrreader.cpp
client_rn/encodesvc/plugins/input/dtdrreader/hxdtdrreader.h
client_rn/encodesvc/plugins/input/dtdrreader/hxdtdrservice.cpp
client/encodesvc/include/ihxtconstants.h
producerapps/installer/root/xmlschemas/job.3.0.xsd
datatype/tools/dtdriver/decoder/audio/Umakefil
datatype/tools/dtdriver/decoder/common/decslcfn.cpp
datatype/tools/dtdriver/decoder/common/pub/decslcfn.h
datatype/tools/dtdriver/decoder/video/vdepacker.cpp
client/encodesvc/engine/encpipeline/inputpipeline.cpp
client/encodesvc/engine/encpipeline/outputpipeline.cpp
client/encodesvc/engine/encpipeline/outputpipeline.h
client/encodesvc/engine/encsession/inputsource.cpp
client/build/BIF/PRODUCER_14.bif
producerapps_rn/installer/producer/make_tempdir
Testing Performed:
================
Unit Tests:
1. enable pass through by set PassThroughVideo="true", PassThroughVideo="true"
Input: only one audio stream, type is AAC.
Output: save as a MP4 file.
Expected: HMP never decode and encode the input stream, just pass through it.
Real result: Yes
2. enable pass through by set PassThroughVideo="true", PassThroughVideo="true"
Input: only one video stream, type is H264.
Output: save as a MP4 file.
Expected: HMP never decode and encode the input stream, just pass through it.
Real result: Yes
3. enable pass through by set PassThroughVideo="true", PassThroughVideo="true"
Input: two input stream, video is H264, audio is AAC
Output: save as a MP4 file.
Expected: HMP never decode and encode the input stream, just pass through it.
Real result: Yes
4. enable pass through by set PassThroughVideo="true", PassThroughVideo="true"
Input: two input stream, video is H264, audio is AAC
Output: RBS.
Expected: HMP never decode and encode the input stream, just pass through it to \
server. Real result: Yes. But there are some warning message.
5. disable pass through by set PassThroughVideo="false", PassThroughVideo="false"
Input: two input stream, video is H264, audio is AAC
Output: save as a MP4 file.
Expected: HMP will decode and encode the input stream.
Real result: Yes
Unit Tests: None
Leak Tests: None
Performance Tests: N/A
Platforms Tested: win32-i386-vc9
Builds Verified: win32-i386-vc9
QA Hints
no
--- NEW FILE: adepacker.cpp ---
/* ***** BEGIN LICENSE BLOCK *****
*
* Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file,
* are subject to the current version of the RealNetworks Public
* Source License (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the current version of the RealNetworks Community
* Source License (the "RCSL") available at
* http://www.helixcommunity.org/content/rcsl, in which case the RCSL
* will apply. You may also obtain the license terms directly from
* RealNetworks. You may not use this file except in compliance with
* the RPSL or, if you have a valid RCSL with RealNetworks applicable
* to this file, the RCSL. Please see the applicable RPSL or RCSL for
* the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the
* portions it created.
*
* This file, and the files included with this file, is distributed
* and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
* ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "hxtypes.h"
#include "hlxclib/string.h"
#include "hxcom.h"
#include "hxplugn.h"
#include "ihxpckts.h"
#include "hxcore.h"
#include "hxformt.h"
#include "hxausvc.h"
#include "hxrasyn.h"
#include "hxbuffer.h"
#include "multilog.h"
#include "pckunpck.h" // SetCStringProperty
#include "plghand2.h"
#include "netbyte.h"
#include "hxtick.h"
#include "rtptypes.h"
#include "hxsrcin.h"
#include "metautil.h"
#include "csrchdlr.h"
#include "stubstrm.h"
#include "adepacker.h"
#if defined(_DEBUG)
#define TRACE_TARGET_FILE 0
#define TRACE_TARGET_DEBUGGER 1
#else
#define TRACE_TARGET_FILE 0
#define TRACE_TARGET_DEBUGGER 0
#endif
// Create an inline MLOG_TRACE() function
#ifndef MLOG_TRACE_COMPILED_OUT
INIT_MULTILOG_GROUP_NO_COREDEBUG(TRACE,
TRACE_TARGET_FILE,
TRACE_TARGET_DEBUGGER,
"sdepacker_trace.log");
#else
#define MLOG_TRACE if(0)
#endif
CAudioSourceDepacketizer::CAudioSourceDepacketizer(IUnknown* pContext) :
CSourceHandler(pContext)
{
MLOG_TRACE("%lu CON CAudioSourceDepacketizer this=0x%08x\n",
HX_GET_BETTERTICKCOUNT(), this);
m_lRefCount = 0;
m_lLastError = 0;
m_pFileHeaderIn = NULL;
m_pStreamHeaderIn = NULL;
m_pFileHeaderOut = NULL;
m_pStreamHeaderOut = NULL;
m_pMimeTypeStr = NULL;
m_pFact = NULL;
m_pDepacker = NULL;
m_pErrorMessages = NULL;
m_pStream = NULL;
m_ulStartTime = 0;
m_ulPreviousPacketTime = 0;
m_ulPacketCount = 0;
m_bMaxSpeed = 0;
m_bProcessHeadersOnly = 0;
m_bSetSrcProperties = 0;
m_bFirstWrite = 1;
if (m_pContext)
{
m_pContext->QueryInterface(IID_IHXCommonClassFactory,
(void**) &m_pFact);
m_pContext->QueryInterface(IID_IHXErrorMessages,
(void**) &m_pErrorMessages);
}
}
CAudioSourceDepacketizer::~CAudioSourceDepacketizer()
{
MLOG_TRACE("%lu DES CAudioSourceDepacketizer this=0x%08x\n",
HX_GET_BETTERTICKCOUNT(), this);
Close();
}
STDMETHODIMP CAudioSourceDepacketizer::QueryInterface(REFIID riid, void** ppvObj)
{
HX_RESULT retVal = HXR_OK;
if (ppvObj)
{
// Set default
*ppvObj = NULL;
// First we try ourselves, then we try our context,
// then we try our base class.
if (IsEqualIID(riid, IID_IUnknown))
{
AddRef();
*ppvObj = (IUnknown*) (IHXPlugin*) this;
}
else
{
// try our base class...
retVal = CSourceHandler::QueryInterface(riid, ppvObj);
// Next try our context
if (FAILED(retVal) && m_pContext)
{
retVal = m_pContext->QueryInterface(riid, ppvObj);
}
}
}
else
{
retVal = HXR_FAIL;
}
return retVal;
}
STDMETHODIMP_(UINT32) CAudioSourceDepacketizer::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
STDMETHODIMP_(UINT32) CAudioSourceDepacketizer::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
// Not sure how this is reconciled with multiple streams being written to a single \
file STDMETHODIMP CAudioSourceDepacketizer::OnFileHeader( HX_RESULT status, \
IHXValues* pValues ) {
MLOG_TRACE("%lu CAudioSourceDepacketizer::OnFileHeader(0x%08x,0x%08x)\n",
HX_GET_BETTERTICKCOUNT(), status, pValues);
HX_RESULT retVal = HXR_OK;
// Check our options. We check them again
// here (we also did in InitSourceHandler())
// in case another object is also holding a ref
// on the options and has changed them since we
// were initialized
m_bProcessHeadersOnly = GetBOOLOption("ProcessHeadersOnly", \
m_bProcessHeadersOnly); m_bMaxSpeed = GetBOOLOption("MaxSpeed", \
m_bMaxSpeed); m_bSetSrcProperties = GetBOOLOption("SetSrcProperties", \
m_bSetSrcProperties); m_ulStartTime = \
GetULONG32Option("StartTime", m_ulStartTime);
if (SUCCEEDED(status) && pValues)
{
// Save the file header.
// XXXMEH - not sure that we'll need this,
// but go ahead and save it for now.
HX_RELEASE(m_pFileHeaderIn);
m_pFileHeaderIn = pValues;
m_pFileHeaderIn->AddRef();
// Create an IHXValues
HX_RELEASE(m_pFileHeaderOut);
retVal = CreateValuesCCF(m_pFileHeaderOut, m_pContext);
if (SUCCEEDED(retVal))
{
IHXBuffer* pBuffer = NULL;
// Set the stream count
m_pFileHeaderOut->SetPropertyULONG32("StreamCount", 1);
// TODO determine which inbound properties need to be propogated on
// Set the flag saying this is not a real datatype
m_pFileHeaderOut->SetPropertyULONG32("IsRealDataType", 0);
m_pFileHeaderIn->GetPropertyCString("AudioFormat", pBuffer);
if (pBuffer)
{
m_pFileHeaderOut->SetPropertyCString("AudioFormat", pBuffer);
HX_RELEASE(pBuffer);
}
// Transfer metadata if present
MetaInfo::CopyAllProperties(m_pFileHeaderOut, m_pFileHeaderIn, \
METAINFO_SET_ALL, FALSE);
// Pass this along to the sink
if (m_pSourceSink)
{
MLOG_TRACE(" sending file header to sink\n");
m_pSourceSink->OnFileHeader(HXR_OK, m_pFileHeaderOut);
}
}
}
else
{
retVal = HXR_FAIL;
}
// If we failed, then still call to the sink
if (FAILED(retVal) && m_pSourceSink)
{
m_pSourceSink->OnFileHeader(retVal, NULL);
m_lLastError = retVal;
}
return retVal;
}
STDMETHODIMP CAudioSourceDepacketizer::OnStreamHeader( HX_RESULT status, IHXValues* \
pValues) {
MLOG_TRACE("%lu CAudioSourceDepacketizer::OnStreamHeader(0x%08x,0x%08x)\n",
HX_GET_BETTERTICKCOUNT(), status, pValues);
HX_RESULT retVal = HXR_FAIL;
if (SUCCEEDED(status) && pValues)
{
// Save the stream header
// XXXMEH - not sure that we'll need this,
// but go ahead and save it for now.
HX_RELEASE(m_pStreamHeaderIn);
m_pStreamHeaderIn = pValues;
m_pStreamHeaderIn->AddRef();
// Check our options. We check them again
// here (we also did in InitSourceHandler() and
// OnFileHeader()) in case another object is also
// holding a ref on the options and has changed them
// since we were initialized,
m_bProcessHeadersOnly = GetBOOLOption("ProcessHeadersOnly", \
m_bProcessHeadersOnly);
m_bMaxSpeed = GetBOOLOption("MaxSpeed", m_bMaxSpeed);
m_bSetSrcProperties = GetBOOLOption("SetSrcProperties", \
m_bSetSrcProperties);
m_ulStartTime = GetULONG32Option("StartTime", m_ulStartTime);
// Load the depacker
HX_RELEASE(m_pDepacker);
retVal = LoadDepackerForStreamHeader(m_pStreamHeaderIn, m_pDepacker);
if (SUCCEEDED(retVal))
{
// Init the depacker
retVal = InitDepacker(m_pDepacker, m_pStreamHeaderIn);
// Get output stream header from depacker
if (SUCCEEDED(retVal))
{
HX_RELEASE(m_pStreamHeaderOut);
retVal = CreateValuesCCF(m_pStreamHeaderOut, m_pContext);
}
if (SUCCEEDED(retVal))
{
retVal = m_pDepacker->GetStreamHeader(m_pStreamHeaderOut);
}
if (SUCCEEDED(retVal))
{
// Transfer metadata if present
MetaInfo::CopyAllProperties(m_pStreamHeaderOut, m_pStreamHeaderIn, \
METAINFO_SET_ALL, FALSE); }
if (SUCCEEDED(retVal) && m_pSourceSink)
{
m_pSourceSink->OnStreamHeader(HXR_OK, m_pStreamHeaderOut);
}
}
}
if (FAILED(retVal) && m_pSourceSink)
{
m_pSourceSink->OnTermination(retVal);
m_lLastError = retVal;
}
return retVal;
}
STDMETHODIMP CAudioSourceDepacketizer::OnStreamDone( HX_RESULT status, UINT16 \
unStreamNumber ) {
HX_RESULT retVal = HXR_OK;
if (FAILED(status) || FAILED(m_lLastError))
{
retVal = HXR_FAIL;
}
if (m_pSourceSink)
{
retVal = m_pSourceSink->OnStreamDone(retVal, unStreamNumber);
}
return retVal;
}
STDMETHODIMP CAudioSourceDepacketizer::OnPacket( HX_RESULT status, IHXPacket* pPacket \
) {
HX_RESULT retVal = HXR_FAIL;
IHXPacket* pOutputPacket = NULL;
m_ulPacketCount++;
if (SUCCEEDED(status) && pPacket && m_pDepacker &&
SUCCEEDED(m_lLastError) && !m_bProcessHeadersOnly)
{
retVal = m_pDepacker->SetPacket(pPacket);
}
if (SUCCEEDED(retVal))
{
// get the depacked frame(s) and send to sink...
while (m_pDepacker->GetPacket(pOutputPacket) == HXR_OK && pOutputPacket)
{
if (m_pSourceSink)
{
m_pSourceSink->OnPacket(HXR_OK, pOutputPacket);
}
HX_RELEASE(pOutputPacket);
}
}
return retVal;
}
STDMETHODIMP CAudioSourceDepacketizer::OnTermination(HX_RESULT status)
{
HX_RESULT retVal = HXR_OK;
AddRef();
// Call our sink with OnTermination
if (m_pSourceSink)
{
retVal = m_pSourceSink->OnTermination(status);
HX_RELEASE(m_pSourceSink);
}
// Release ourselves
Release();
return retVal;
}
STDMETHODIMP CAudioSourceDepacketizer::Close()
{
HX_RELEASE(m_pFileHeaderIn);
HX_RELEASE(m_pStreamHeaderIn);
HX_RELEASE(m_pFileHeaderOut);
HX_RELEASE(m_pStreamHeaderOut);
HX_RELEASE(m_pMimeTypeStr);
HX_RELEASE(m_pFact);
HX_RELEASE(m_pDepacker);
HX_RELEASE(m_pStream);
HX_RELEASE(m_pErrorMessages);
return HXR_OK;
}
STDMETHODIMP CAudioSourceDepacketizer::InitSourceHandler(IHXSourceInput* pSourceSink,
IHXValues* pOptions)
{
HX_RESULT retVal = CSourceHandler::InitSourceHandler(pSourceSink, pOptions);
// Check our options
m_bProcessHeadersOnly = GetBOOLOption("ProcessHeadersOnly", \
m_bProcessHeadersOnly); m_bMaxSpeed = GetBOOLOption("MaxSpeed", \
m_bMaxSpeed); m_bSetSrcProperties = GetBOOLOption("SetSrcProperties", \
m_bSetSrcProperties); m_ulStartTime = \
GetULONG32Option("StartTime", m_ulStartTime);
return retVal;
}
HX_RESULT CAudioSourceDepacketizer::Create(IHXSourceHandler** pSourceHandler,
IUnknown* pContext)
{
HX_RESULT retVal = HXR_OK;
if (pSourceHandler)
{
// Create the source handler
CAudioSourceDepacketizer* pHandler = new CAudioSourceDepacketizer(pContext);
if (pHandler)
{
// AddRef the source handler
pHandler->AddRef();
// Set the out parameter
*pSourceHandler = pHandler;
}
else
{
retVal = HXR_OUTOFMEMORY;
}
}
else
{
retVal = HXR_FAIL;
}
return retVal;
}
HX_RESULT CAudioSourceDepacketizer::LoadDepackerForStreamHeader(IHXValues* \
pStreamHeader,
REF(IHXPayloadFormatObject*) rpDepacker)
{
HX_RESULT retVal = HXR_OK;
if (pStreamHeader && m_pContext)
{
// Get the mime type from the stream header
HX_RELEASE(m_pMimeTypeStr);
retVal = m_pStreamHeaderIn->GetPropertyCString("MimeType", m_pMimeTypeStr);
if (SUCCEEDED(retVal))
{
// QI our context for IHXPlugin2Handler
IHXPlugin2Handler* pHandler = NULL;
retVal = m_pContext->QueryInterface(IID_IHXPlugin2Handler,
(void**) &pHandler);
if (SUCCEEDED(retVal))
{
// Find the plugin for this mime type
IUnknown* pUnk = NULL;
const char* pLoadPhase = "find";
retVal = pHandler->FindPluginUsingStrings(PLUGIN_CLASS,
PLUGIN_DEPACKER_TYPE,
PLUGIN_DEPACKER_MIME,
(char*) \
m_pMimeTypeStr->GetBuffer(),
//"video/x-pn-realvideo",
NULL,
NULL,
pUnk);
if (SUCCEEDED(retVal))
{
// QI for IHXPlugin
IHXPlugin* pPlugin = NULL;
retVal = pUnk->QueryInterface(IID_IHXPlugin,
(void**) &pPlugin);
pLoadPhase = "initialize";
if (SUCCEEDED(retVal))
{
// Init the plugin with the context
retVal = pPlugin->InitPlugin(m_pContext);
if (SUCCEEDED(retVal))
{
// QI for IHXPayloadFormatObject
HX_RELEASE(rpDepacker);
retVal = pUnk->QueryInterface(IID_IHXPayloadFormatObject,
(void**) &rpDepacker);
}
}
HX_RELEASE(pPlugin);
}
if (FAILED(retVal))
{
if (m_pErrorMessages)
{
char* pErrorMsg = new char [m_pMimeTypeStr->GetSize() + 100];
if (pErrorMsg)
{
sprintf(pErrorMsg, /* Flawfinder: ignore */
"Failed to %s depacketizer for Stream Mime-Type: \
%s", pLoadPhase,
(char*) m_pMimeTypeStr->GetBuffer());
if (pErrorMsg)
{
m_pErrorMessages->Report(HXLOG_ERR,
retVal,
0, // user code
pErrorMsg,
NULL); // more info URL.
}
delete [] pErrorMsg;
}
}
}
HX_RELEASE(pUnk);
}
HX_RELEASE(pHandler);
}
}
else
{
retVal = HXR_FAIL;
}
return retVal;
}
HX_RESULT CAudioSourceDepacketizer::InitDepacker(IHXPayloadFormatObject* pDepacker,
IHXValues* pStreamHeader)
{
HX_RESULT retVal = HXR_FAIL;
if (pDepacker && m_pContext)
{
retVal = pDepacker->SetStreamHeader(pStreamHeader);
}
return retVal;
}
HX_RESULT CAudioSourceDepacketizer::MakePacket(IHXBuffer* pBuffer,
UINT32 ulTime,
UINT16 usStreamNumber,
UINT8 ucASMFlags,
UINT16 usASMRuleNumber,
REF(IHXPacket*) rpPacket)
{
HX_RESULT retVal = HXR_FAIL;
if (pBuffer && m_pFact)
{
IHXPacket* pPacket = NULL;
retVal = m_pFact->CreateInstance(CLSID_IHXPacket, (void**) &pPacket);
if (SUCCEEDED(retVal))
{
retVal = pPacket->Set(pBuffer, ulTime, usStreamNumber,
ucASMFlags, usASMRuleNumber);
if (SUCCEEDED(retVal))
{
rpPacket = pPacket;
rpPacket->AddRef();
}
}
HX_RELEASE(pPacket);
}
return retVal;
}
HXBOOL CAudioSourceDepacketizer::GetBOOLOption(const char* pszStr, HXBOOL bDefault)
{
HXBOOL bRet = bDefault;
if (m_pOptions)
{
UINT32 ulValue = 0;
HX_RESULT rv = m_pOptions->GetPropertyULONG32(pszStr, ulValue);
if (SUCCEEDED(rv) && ulValue != 0)
{
bRet = TRUE;
}
else
{
bRet = FALSE;
}
}
return bRet;
}
ULONG32 CAudioSourceDepacketizer::GetULONG32Option(const char* pszStr, ULONG32 \
ulDefault) {
ULONG32 ulRet = ulDefault;
if (m_pOptions)
{
UINT32 ulValue = 0;
HX_RESULT rv = m_pOptions->GetPropertyULONG32(pszStr, ulValue);
if (SUCCEEDED(rv))
{
ulRet = ulValue;
}
}
return ulRet;
}
_______________________________________________
Datatype-cvs mailing list
Datatype-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/datatype-cvs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic