From: Craig S. <cso...@us...> - 2006-07-31 09:09:26
|
Update of /cvsroot/openh323/opal/plugins/video/H.261-vic In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv16546/plugins/video/H.261-vic Added Files: Makefile.in h261vic.cxx h261vic.vcproj h261vic_2005.vcproj Log Message: Checkin of validated codec used during development --- NEW FILE: h261vic_2005.vcproj --- <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" Version="8.00" Name="h261vic" ProjectGUID="{4A1B92CB-CA8E-4511-A1D5-B0A322FDE67C}" > <Platforms> <Platform Name="Win32" /> </Platforms> <ToolFiles> </ToolFiles> <Configurations> <Configuration Name="Release|Win32" OutputDirectory="..\..\Release" IntermediateDirectory="..\..\Release\GSM" ConfigurationType="2" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="2" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" PreprocessorDefinitions="NDEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" TypeLibraryName=".\..\Release/h261vic.tlb" HeaderFileName="" /> <Tool Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_CODEC_DLL_EXPORTS" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" RuntimeTypeInfo="true" ProgramDataBaseFileName="$(IntDir)/$(TargetName).pdb" WarningLevel="3" SuppressStartupBanner="true" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="3081" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLinkerTool" IgnoreImportLibrary="true" OutputFile="../../Release/h261vic_pwplugin.dll" LinkIncremental="1" SuppressStartupBanner="true" ImportLibrary="$(IntDir)/$(TargetName).lib" TargetMachine="1" /> <Tool Name="VCALinkTool" /> <Tool Name="VCManifestTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> <Tool Name="VCFxCopTool" /> <Tool Name="VCAppVerifierTool" /> <Tool Name="VCWebDeploymentTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> <Configuration Name="Debug|Win32" OutputDirectory="..\..\Debug" IntermediateDirectory="..\..\Debug\H261-vic" ConfigurationType="2" InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="2" > <Tool Name="VCPreBuildEventTool" /> <Tool Name="VCCustomBuildTool" /> <Tool Name="VCXMLDataGeneratorTool" /> <Tool Name="VCWebServiceProxyGeneratorTool" /> <Tool Name="VCMIDLTool" PreprocessorDefinitions="_DEBUG" MkTypLibCompatible="true" SuppressStartupBanner="true" TargetEnvironment="1" TypeLibraryName=".\..\Debug/h261vic.tlb" HeaderFileName="" /> <Tool Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_CODEC_DLL_EXPORTS" BasicRuntimeChecks="3" RuntimeLibrary="3" RuntimeTypeInfo="true" ProgramDataBaseFileName="$(IntDir)/$(TargetName).pdb" WarningLevel="4" SuppressStartupBanner="true" DebugInformationFormat="3" /> <Tool Name="VCManagedResourceCompilerTool" /> <Tool Name="VCResourceCompilerTool" PreprocessorDefinitions="_DEBUG" Culture="3081" /> <Tool Name="VCPreLinkEventTool" /> <Tool Name="VCLinkerTool" IgnoreImportLibrary="true" AdditionalDependencies="wsock32.lib" OutputFile="../../Debug/h261vic_pwplugin.dll" LinkIncremental="1" SuppressStartupBanner="true" GenerateDebugInformation="true" ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb" ImportLibrary="$(IntDir)/$(TargetName).lib" TargetMachine="1" /> <Tool Name="VCALinkTool" /> <Tool Name="VCManifestTool" /> <Tool Name="VCXDCMakeTool" /> <Tool Name="VCBscMakeTool" /> <Tool Name="VCFxCopTool" /> <Tool Name="VCAppVerifierTool" /> <Tool Name="VCWebDeploymentTool" /> <Tool Name="VCPostBuildEventTool" /> </Configuration> </Configurations> <References> </References> <Files> <Filter Name="Source Files" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > <File RelativePath=".\h261vic.cxx" > </File> </Filter> <Filter Name="VIC Files" Filter=".c" > <Filter Name="C Files" > <File RelativePath=".\vic\bv.c" > </File> <File RelativePath=".\vic\huffcode.c" > </File> </Filter> <Filter Name="CXX Files" > <File RelativePath=".\vic\dct.cxx" > </File> <File RelativePath=".\vic\encoder-h261.cxx" > </File> <File RelativePath=".\vic\p64.cxx" > </File> <File RelativePath=".\vic\p64encoder.cxx" > </File> <File RelativePath=".\vic\transmitter.cxx" > </File> <File RelativePath=".\vic\vid_coder.cxx" > </File> </Filter> <Filter Name="H Files" > <File RelativePath=".\vic\bsd-endian.h" > </File> <File RelativePath=".\vic\config.h" > </File> <File RelativePath=".\vic\dct.h" > </File> <File RelativePath=".\vic\encoder-h261.h" > </File> <File RelativePath=".\vic\grabber.h" > </File> <File RelativePath=".\vic\p64-huff.h" > </File> <File RelativePath=".\vic\p64.h" > </File> <File RelativePath=".\vic\p64encoder.h" > </File> <File RelativePath=".\vic\transmitter.h" > </File> <File RelativePath=".\vic\vid_coder.h" > </File> </Filter> </Filter> </Files> <Globals> </Globals> </VisualStudioProject> --- NEW FILE: Makefile.in --- # # Makefile for GSM 06.10 # # Copyright (C) 2004 Post Increment, All Rights Reserved # # The contents of this file are subject to the Mozilla Public License # Version 1.0 (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 Open H323 library. # # The Initial Developer of the Original Code is Post Increment # # Contributor(s): ______________________________________. # # $Log: Makefile.in,v $ # Revision 1.1 2006/07/31 09:09:21 csoutheren # Checkin of validated codec used during development # # Revision 1.11 2006/02/20 08:54:32 csoutheren # Fixed problem with Makefile. WTF did this come from? :) # # Revision 1.10 2006/02/09 23:42:54 csoutheren # Added check for system gsm library # # Revision 1.9 2004/08/24 14:15:12 csoutheren # Fixed potential problems with MS-GSM # # Revision 1.8 2004/08/22 04:20:18 csoutheren # Added -fPIC to build commands to fix problems on 64 bit platforms # Thanks to Klaus Kaempf # # Revision 1.7 2004/06/24 23:33:17 csoutheren # Changed Makefiles to ensure all plugins have correct suffix # # Revision 1.6 2004/06/17 23:14:59 csoutheren # Fixed error when using "make install" with embedded GSM # Thanks to Matthias Weber # # Revision 1.5 2004/05/18 22:24:24 csoutheren # Initiali support for embedded codecs # # Revision 1.4 2004/05/03 11:08:30 csoutheren # Modified to allow plugins to be created on various platforms # # Revision 1.3 2004/05/02 13:57:05 rjongbloed # Fixed building local GSM if no system library # # Revision 1.2 2004/04/29 14:47:59 csoutheren # Reconfigured plugin makefiles per suggestions from Damien Sandras # Changed install targets to use $(INSTALL) # # Revision 1.1 2004/04/29 10:48:55 csoutheren # Initial version # # Revision 1.1 2004/04/27 09:59:27 csoutheren # Updated codec specific Makefiles # # # STDCCFLAGS += -fPIC PREFIX=@INSTALLPREFIX@ exec_prefix = ${PREFIX} LIBDIR=@LIBDIR@ H323_SYSTEM_GSM=@H323_SYSTEM_GSM@ H323_EMBEDDED_GSM=@H323_EMBEDDED_GSM@ CC=@CC@ CFLAGS=@CFLAGS@ CXX=@CXX@ LDSO=@LDSO@ ifndef PREFIX PREFIX=/usr/local endif SONAME = gsm0610 SRCDIR = ./src OBJDIR = ./obj SRCS += gsm06_10_codec.c ifeq ($(H323_SYSTEM_GSM),0) SRCS += $(SRCDIR)/gsm_create.c \ $(SRCDIR)/gsm_destroy.c \ $(SRCDIR)/gsm_decode.c \ $(SRCDIR)/gsm_encode.c \ $(SRCDIR)/gsm_option.c \ $(SRCDIR)/code.c \ $(SRCDIR)/decode.c \ $(SRCDIR)/add.c \ $(SRCDIR)/gsm_lpc.c \ $(SRCDIR)/rpe.c \ $(SRCDIR)/preprocess.c \ $(SRCDIR)/long_term.c \ $(SRCDIR)/short_term.c \ $(SRCDIR)/table.c EXTRALIBS = else EXTRALIBS = -lgsm endif vpath %.o $(OBJDIR) vpath %.c $(SRCDIR) ifeq ($(H323_EMBEDDED_GSM),1) EXTRACCFLAGS=-DOPAL_STATIC_CODEC endif $(OBJDIR)/%.o : %.c @mkdir -p $(OBJDIR) >/dev/null 2>&1 $(CC) -I../../../include -I./inc -DWAV49 -DNeedFunctionPrototypes=1 $(EXTRACCFLAGS) $(STDCCFLAGS) $(OPTCCFLAGS) $(CFLAGS) -c $< -o $@ PLUGIN = ./$(SONAME)_audio_pwplugin.so STATIC = ./lib$(SONAME)_audio_s.a OBJECTS = $(addprefix $(OBJDIR)/,$(patsubst %.c,%.o,$(notdir $(SRCS)))) ifeq ($(H323_EMBEDDED_GSM),1) $(STATIC): $(OBJECTS) $(AR) rcs $@ $^ install: uninstall: else $(PLUGIN): $(OBJECTS) $(CC) $(LDSO)$(SONAME) -o $@ $^ $(EXTRALIBS) endif install: mkdir -p $(DESTDIR)$(LIBDIR)/pwlib/codecs/audio/ cp $(PLUGIN) $(DESTDIR)$(LIBDIR)/pwlib/codecs/audio/ uninstall: rm -f $(DESTDIR)$(LIBDIR)/pwlib/codecs/audio/$(PLUGIN) clean: rm -f $(OBJECTS) $(PLUGIN) ########################################### --- NEW FILE: h261vic.cxx --- /* * H.261 Plugin codec for OpenH323/OPAL * * Copyright (C) 2005 Post Increment, All Rights Reserved * * This code is based on the file h261codec.cxx from the OPAL project released * under the MPL 1.0 license which contains the following: * * Copyright (c) 1998-2000 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (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 Open H323 Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): Michele Piccini (mi...@pi...) * Derek Smithies (de...@in...) * * $Log: h261vic.cxx,v $ * Revision 1.2 2006/07/31 09:09:21 csoutheren * Checkin of validated codec used during development * * Revision 1.1.2.9 2006/04/26 08:03:57 csoutheren * H.263 encoding and decoding now working from plugin for both SIP and H.323 * * Revision 1.1.2.8 2006/04/26 05:09:57 csoutheren * Cleanup bit rate settings * * Revision 1.1.2.7 2006/04/25 01:07:00 csoutheren * Rename SIP options * * Revision 1.1.2.6 2006/04/24 09:08:49 csoutheren * Cleanups * * Revision 1.1.2.5 2006/04/21 05:42:49 csoutheren * Checked in forgotten changes to fix iFrame requests * * Revision 1.1.2.4 2006/04/19 07:52:30 csoutheren * Add ability to have SIP-only and H.323-only codecs, and implement for H.261 * * Revision 1.1.2.3 2006/04/19 05:56:23 csoutheren * Fix marker bits on outgoing video * * Revision 1.1.2.2 2006/04/19 04:59:29 csoutheren * Allow specification of CIF and QCIF capabilities * * Revision 1.1.2.1 2006/04/06 01:17:16 csoutheren * Initial version of H.261 video codec plugin for OPAL * */ /* Notes ----- This codec implements a H.261 encoder and decoder with RTP packaging as per RFC 2032 "RTP Payload Format for H.261 Video Streams". As per this specification, The RTP payload code is always set to 31 The encoder only creates I-frames The decoder can accept either I-frames or P-frames There are seperate encoder/decoder pairs for H.323, which ensures that the decoder always knows whether it will be receiving CIF or QCIF data There is a seperate encoder/decoder pair for SIP */ #include <codec/opalplugin.h> extern "C" { PLUGIN_CODEC_IMPLEMENT(VIC_H261) }; #include <stdlib.h> #ifdef _WIN32 //#include <windows.h> #include <malloc.h> #endif #include <string.h> //#ifdef _MSC_VER //#pragma warning(disable:4100) //#endif #define BEST_ENCODER_QUALITY 1 #define WORST_ENCODER_QUALITY 31 #define DEFAULT_FILL_LEVEL 5 #define RTP_RFC2032_PAYLOAD 31 #define RTP_DYNAMIC_PAYLOAD 96 #define H261_CLOCKRATE 90000 #define H261_BITRATE 621700 typedef unsigned char u_char; typedef unsigned short u_short; typedef unsigned int u_int; #include "vic/p64.h" #include "vic/p64encoder.h" ///////////////////////////////////////////////////////////////// // // define a class to implement a critical section mutex // based on PCriticalSection from PWLib class CriticalSection { public: CriticalSection() { #ifdef _WIN32 ::InitializeCriticalSection(&criticalSection); #else ::sem_init(&sem, 0, 1); #endif } ~CriticalSection() { #ifdef _WIN32 ::DeleteCriticalSection(&criticalSection); #else ::sem_destroy(&sem); #endif } void Wait() { #ifdef _WIN32 ::EnterCriticalSection(&criticalSection); #else ::sem_wait(&sem); #endif } void Signal() { #ifdef _WIN32 ::LeaveCriticalSection(&criticalSection); #else ::sem_post(&sem); #endif } private: CriticalSection & operator=(const CriticalSection &) { return *this; } #ifdef _WIN32 mutable CRITICAL_SECTION criticalSection; #else mutable sem_t sem; #endif }; class WaitAndSignal { public: inline WaitAndSignal(const CriticalSection & cs) : sync((CriticalSection &)cs) { sync.Wait(); } ~WaitAndSignal() { sync.Signal(); } WaitAndSignal & operator=(const WaitAndSignal &) { return *this; } protected: CriticalSection & sync; }; ///////////////////////////////////////////////////////////////////////////// // // define some simple RTP packet routines // #define RTP_MIN_HEADER_SIZE 12 class RTPFrame { public: RTPFrame(const unsigned char * _packet, int _packetLen) : packet((unsigned char *)_packet), packetLen(_packetLen) { } RTPFrame(unsigned char * _packet, int _packetLen, unsigned char payloadType) : packet(_packet), packetLen(_packetLen) { if (packetLen > 0) packet[0] = 0x80; // set version, no extensions, zero contrib count SetPayloadType(payloadType); } inline unsigned long GetLong(int offs) const { if (offs + 4 > packetLen) return 0; return (packet[offs + 0] << 24) + (packet[offs+1] << 16) + (packet[offs+2] << 8) + packet[offs+3]; } inline void SetLong(int offs, unsigned long n) { if (offs + 4 <= packetLen) { packet[offs + 0] = (BYTE)((n >> 24) & 0xff); packet[offs + 1] = (BYTE)((n >> 16) & 0xff); packet[offs + 2] = (BYTE)((n >> 8) & 0xff); packet[offs + 3] = (BYTE)(n & 0xff); } } inline unsigned short GetShort(int offs) const { if (offs + 2 > packetLen) return 0; return (packet[offs + 0] << 8) + packet[offs + 1]; } inline void SetShort(int offs, unsigned short n) { if (offs + 2 <= packetLen) { packet[offs + 0] = (BYTE)((n >> 8) & 0xff); packet[offs + 1] = (BYTE)(n & 0xff); } } inline int GetPacketLen() const { return packetLen; } inline unsigned GetVersion() const { return (packetLen < 1) ? 0 : (packet[0]>>6)&3; } inline bool GetExtension() const { return (packetLen < 1) ? 0 : (packet[0]&0x10) != 0; } inline bool GetMarker() const { return (packetLen < 2) ? FALSE : ((packet[1]&0x80) != 0); } inline unsigned char GetPayloadType() const { return (packetLen < 2) ? FALSE : (packet[1] & 0x7f); } inline unsigned short GetSequenceNumber() const { return GetShort(2); } inline unsigned long GetTimestamp() const { return GetLong(4); } inline unsigned long GetSyncSource() const { return GetLong(8); } inline int GetContribSrcCount() const { return (packetLen < 1) ? 0 : (packet[0]&0xf); } inline int GetExtensionSize() const { return !GetExtension() ? 0 : GetShort(RTP_MIN_HEADER_SIZE + 4*GetContribSrcCount() + 2); } inline int GetExtensionType() const { return !GetExtension() ? -1 : GetShort(RTP_MIN_HEADER_SIZE + 4*GetContribSrcCount()); } inline int GetPayloadSize() const { return packetLen - GetHeaderSize(); } inline const unsigned char * GetPayloadPtr() const { return packet + GetHeaderSize(); } inline unsigned int GetHeaderSize() const { unsigned int sz = RTP_MIN_HEADER_SIZE + 4*GetContribSrcCount(); if (GetExtension()) sz += 4 + GetExtensionSize(); return sz; } inline void SetMarker(bool m) { if (packetLen >= 2) packet[1] = (packet[1] & 0x7f) | (m ? 0x80 : 0x00); } inline void SetPayloadType(unsigned char t) { if (packetLen >= 2) packet[1] = (packet[1] & 0x80) | (t & 0x7f); } inline void SetSequenceNumber(unsigned short v) { SetShort(2, v); } inline void SetTimestamp(unsigned long n) { SetLong(4, n); } inline void SetSyncSource(unsigned long n) { SetLong(8, n); } inline void SetPayloadSize(int payloadSize) { packetLen = GetHeaderSize() + payloadSize; } protected: unsigned char * packet; int packetLen; }; ///////////////////////////////////////////////////////////////////////////// static const char * default_sip_options[][3] = { { "h323_cifMPI", "<4" , "i" }, { "h323_qcifMPI", "<2" , "i" }, // { "Max Bit Rate", "<621700" , "i" }, { NULL, NULL, NULL } }; static const char * default_cif_h261_options[][3] = { { "h323_cifMPI", "<4" , "i" }, // { "Max Bit Rate", "<621700" , "i" }, { NULL, NULL, NULL } }; static const char * default_qcif_h261_options[][3] = { { "h323_qcifMPI", "<2" , "i" }, // { "Max Bit Rate", "<621700" , "i" }, { NULL, NULL, NULL } }; static int get_xcif_options(void * context, void * parm, unsigned * parmLen, const char ** default_parms) { if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char **)) return 0; const char ***options = (const char ***)parm; if (context == NULL) { *options = default_parms; return 1; } return 0; } static int coder_get_cif_options( const PluginCodec_Definition * , void * context, const char * , void * parm, unsigned * parmLen) { return get_xcif_options(context, parm, parmLen, &default_cif_h261_options[0][0]); } static int coder_get_qcif_options( const PluginCodec_Definition * , void * context, const char * , void * parm, unsigned * parmLen) { return get_xcif_options(context, parm, parmLen, &default_qcif_h261_options[0][0]); } static int coder_get_sip_options( const PluginCodec_Definition * , void * context , const char * , void * parm , unsigned * parmLen) { return get_xcif_options(context, parm, parmLen, &default_sip_options[0][0]); } ///////////////////////////////////////////////////////////////////////////// class H261EncoderContext { public: P64Encoder * videoEncoder; //PTimeInterval newTime; unsigned frameWidth; unsigned frameHeight; unsigned maxOutputSize; bool forceIFrame; int videoQuality; unsigned long lastTimeStamp; CriticalSection mutex; H261EncoderContext() { frameWidth = frameHeight = 0; maxOutputSize = 0; videoEncoder = new P64Encoder(BEST_ENCODER_QUALITY, DEFAULT_FILL_LEVEL); forceIFrame = FALSE; videoQuality = 10; } ~H261EncoderContext() { delete videoEncoder; } void SetFrameSize(int w, int h) { frameWidth = w; frameHeight = h; videoEncoder->SetSize(frameWidth, frameHeight); maxOutputSize = (frameWidth * frameHeight * 12) / 8; } int EncodeFrames(const BYTE * src, unsigned & srcLen, BYTE * dst, unsigned & dstLen, unsigned int & flags) { WaitAndSignal m(mutex); // create RTP frame from source buffer RTPFrame srcRTP(src, srcLen); // create RTP frame from destination buffer RTPFrame dstRTP(dst, dstLen, RTP_RFC2032_PAYLOAD); dstLen = 0; // return more pending data frames, if any if (videoEncoder->MoreToIncEncode()) { unsigned payloadLength = 0; videoEncoder->IncEncodeAndGetPacket((u_char *)dstRTP.GetPayloadPtr(), payloadLength); //get next packet on list dstLen = SetEncodedPacket(dstRTP, !videoEncoder->MoreToIncEncode(), RTP_RFC2032_PAYLOAD, lastTimeStamp, payloadLength, flags); return 1; } // // from here on, this is encoding a new frame // // get the timestamp we will be using for the rest of the frame lastTimeStamp = srcRTP.GetTimestamp(); // update the video quality videoEncoder->SetQualityLevel(videoQuality); // get and validate header if (srcRTP.GetPayloadSize() < sizeof(PluginCodec_Video_FrameHeader)) { //PTRACE(1,"H261\tVideo grab too small"); return 0; } PluginCodec_Video_FrameHeader * header = (PluginCodec_Video_FrameHeader *)srcRTP.GetPayloadPtr(); if (header->x != 0 && header->y != 0) { //PTRACE(1,"H261\tVideo grab of partial frame unsupported"); return 0; } // make sure the incoming frame is big enough for the specified frame size if (srcRTP.GetPayloadSize() < (int)(sizeof(PluginCodec_Video_FrameHeader) + frameWidth*frameHeight*12/8)) { //PTRACE(1,"H261\tPayload of grabbed frame too small for full frame"); return 0; } // if the incoming data has changed size, tell the encoder if (frameWidth != header->width || frameHeight != header->height) { frameWidth = header->width; frameHeight = header->height; videoEncoder->SetSize(frameWidth, frameHeight); } // "grab" the frame memcpy(videoEncoder->GetFramePtr(), header->data, frameWidth*frameHeight*12/8); // force I-frame, if requested if (forceIFrame || (flags & PluginCodec_CoderForceIFrame) != 0) { videoEncoder->FastUpdatePicture(); forceIFrame = FALSE; } // preprocess the data videoEncoder->PreProcessOneFrame(); // get next frame from list created by preprocessor if (!videoEncoder->MoreToIncEncode()) dstLen = 0; else { unsigned payloadLength = 0; videoEncoder->IncEncodeAndGetPacket((u_char *)dstRTP.GetPayloadPtr(), payloadLength); dstLen = SetEncodedPacket(dstRTP, !videoEncoder->MoreToIncEncode(), RTP_RFC2032_PAYLOAD, lastTimeStamp, payloadLength, flags); } return 1; } protected: unsigned SetEncodedPacket(RTPFrame & dstRTP, bool isLast, unsigned char payloadCode, unsigned long lastTimeStamp, unsigned payloadLength, unsigned & flags); }; unsigned H261EncoderContext::SetEncodedPacket(RTPFrame & dstRTP, bool isLast, unsigned char payloadCode, unsigned long lastTimeStamp, unsigned payloadLength, unsigned & flags) { dstRTP.SetPayloadSize(payloadLength); dstRTP.SetMarker(isLast); dstRTP.SetPayloadType(payloadCode); dstRTP.SetTimestamp(lastTimeStamp); flags = 0; flags |= isLast ? PluginCodec_ReturnCoderLastFrame : 0; // marker bit on last frame of video flags |= PluginCodec_ReturnCoderIFrame; // sadly, this encoder *always* returns I-frames :( return dstRTP.GetPacketLen(); } static void * create_encoder(const struct PluginCodec_Definition * /*codec*/) { return new H261EncoderContext; } static int encoder_set_options( const PluginCodec_Definition * , void *, const char * , void *, unsigned * ) { //H261EncoderContext * context = (H261EncoderContext *)_context; return 1; } static void destroy_encoder(const struct PluginCodec_Definition * /*codec*/, void * _context) { H261EncoderContext * context = (H261EncoderContext *)_context; delete context; } static int codec_encoder(const struct PluginCodec_Definition * , void * _context, const void * from, unsigned * fromLen, void * to, unsigned * toLen, unsigned int * flag) { H261EncoderContext * context = (H261EncoderContext *)_context; return context->EncodeFrames((const BYTE *)from, *fromLen, (BYTE *)to, *toLen, *flag); } static int encoder_get_output_data_size(const PluginCodec_Definition * codec, void *, const char *, void *, unsigned *) { // this is really frame height * frame width; return codec->samplesPerFrame * codec->bytesPerFrame * 3 / 2; } static PluginCodec_ControlDefn cifEncoderControls[] = { { "get_codec_options", coder_get_cif_options }, { "set_codec_options", encoder_set_options }, { "get_output_data_size", encoder_get_output_data_size }, { NULL } }; static PluginCodec_ControlDefn qcifEncoderControls[] = { { "get_codec_options", coder_get_qcif_options }, { "set_codec_options", encoder_set_options }, { "get_output_data_size", encoder_get_output_data_size }, { NULL } }; static PluginCodec_ControlDefn sipEncoderControls[] = { { "get_codec_options", coder_get_sip_options }, { "set_codec_options", encoder_set_options }, { "get_output_data_size", encoder_get_output_data_size }, { NULL } }; ///////////////////////////////////////////////////////////////////////////// class H261DecoderContext { public: P64Decoder * videoDecoder; WORD expectedSequenceNumber; BYTE * rvts; int ndblk, nblk; int now; bool packetReceived; unsigned frameWidth; unsigned frameHeight; CriticalSection mutex; public: H261DecoderContext() { expectedSequenceNumber = 0; nblk = ndblk = 0; rvts = NULL; now = 1; packetReceived = FALSE; frameWidth = frameHeight = 0; // Create the actual decoder videoDecoder = new FullP64Decoder(); videoDecoder->marks(rvts); } ~H261DecoderContext() { if (rvts) delete rvts; delete videoDecoder; } int DecodeFrames(const BYTE * src, unsigned & srcLen, BYTE * dst, unsigned & dstLen, unsigned int & flags) { WaitAndSignal mutex(mutex); // create RTP frame from source buffer RTPFrame srcRTP(src, srcLen); // create RTP frame from destination buffer RTPFrame dstRTP(dst, dstLen, 0); dstLen = 0; flags = 0; // Check for lost packets to help decoder bool lostPreviousPacket = FALSE; if (expectedSequenceNumber != 0 && expectedSequenceNumber != srcRTP.GetSequenceNumber()) { lostPreviousPacket = TRUE; //PTRACE(3,"H261\tDetected loss of one video packet. " // << expectedSequenceNumber << " != " // << src.GetSequenceNumber() << " Will recover."); } expectedSequenceNumber = (WORD)(srcRTP.GetSequenceNumber()+1); videoDecoder->mark(now); if (!videoDecoder->decode(srcRTP.GetPayloadPtr(), srcRTP.GetPayloadSize(), lostPreviousPacket)) { flags = PluginCodec_ReturnCoderRequestIFrame; return 1; } //Check for a resize - can change at any time! if (frameWidth != (unsigned)videoDecoder->width() || frameHeight != (unsigned)videoDecoder->height()) { frameWidth = videoDecoder->width(); frameHeight = videoDecoder->height(); nblk = (frameWidth * frameHeight) / 64; delete [] rvts; rvts = new BYTE[nblk]; memset(rvts, 0, nblk); videoDecoder->marks(rvts); } // Have not built an entire frame yet if (!srcRTP.GetMarker()) return 1; videoDecoder->sync(); ndblk = videoDecoder->ndblk(); int wraptime = now ^ 0x80; BYTE * ts = rvts; int k; for (k = nblk; --k >= 0; ++ts) { if (*ts == wraptime) *ts = (BYTE)now; } now = (now + 1) & 0xff; int frameBytes = (frameWidth * frameHeight * 12) / 8; dstRTP.SetPayloadSize(sizeof(PluginCodec_Video_FrameHeader) + frameBytes); dstRTP.SetPayloadType(RTP_DYNAMIC_PAYLOAD); dstRTP.SetMarker(true); PluginCodec_Video_FrameHeader * frameHeader = (PluginCodec_Video_FrameHeader *)dstRTP.GetPayloadPtr(); frameHeader->x = frameHeader->y = 0; frameHeader->width = frameWidth; frameHeader->height = frameHeight; memcpy(frameHeader->data, videoDecoder->GetFramePtr(), frameBytes); videoDecoder->resetndblk(); dstLen = dstRTP.GetPacketLen(); flags = PluginCodec_ReturnCoderLastFrame | PluginCodec_ReturnCoderIFrame; // TODO: THIS NEEDS TO BE CHANGED TO DO CORRECT I-FRAME DETECTION return 1; } }; static void * create_decoder(const struct PluginCodec_Definition *) { return new H261DecoderContext; } static int decoder_set_options( const struct PluginCodec_Definition *, void * _context, const char *, void * parm, unsigned * parmLen) { H261DecoderContext * context = (H261DecoderContext *)_context; if (parmLen == NULL || *parmLen != sizeof(const char **)) return 0; // get the "frame width" media format parameter to use as a hint for the encoder to start off if (parm != NULL) { const char ** options = (const char **)parm; int i; int frameWidth = 0; for (i = 0; options[i] != NULL; i += 2) { if (strcmpi(options[i], "Frame Width") == 0) frameWidth = atoi(options[i+1]); } context->videoDecoder->fmt_ = (frameWidth == QCIF_WIDTH) ? IT_QCIF : IT_CIF; context->videoDecoder->init(); } return 1; } static void destroy_decoder(const struct PluginCodec_Definition * /*codec*/, void * _context) { H261DecoderContext * context = (H261DecoderContext *)_context; delete context; } static int codec_decoder(const struct PluginCodec_Definition *, void * _context, const void * from, unsigned * fromLen, void * to, unsigned * toLen, unsigned int * flag) { H261DecoderContext * context = (H261DecoderContext *)_context; return context->DecodeFrames((const BYTE *)from, *fromLen, (BYTE *)to, *toLen, *flag); } static int decoder_get_output_data_size(const PluginCodec_Definition * codec, void *, const char *, void *, unsigned *) { // this is really frame height * frame width; return sizeof(PluginCodec_Video_FrameHeader) + ((codec->samplesPerFrame * codec->bytesPerFrame * 3) / 2); } static PluginCodec_ControlDefn cifDecoderControls[] = { { "get_codec_options", coder_get_cif_options }, { "set_codec_options", decoder_set_options }, { "get_output_data_size", decoder_get_output_data_size }, { NULL } }; static PluginCodec_ControlDefn qcifDecoderControls[] = { { "get_codec_options", coder_get_qcif_options }, { "set_codec_options", decoder_set_options }, { "get_output_data_size", decoder_get_output_data_size }, { NULL } }; static PluginCodec_ControlDefn sipDecoderControls[] = { { "get_codec_options", coder_get_sip_options }, { "set_codec_options", decoder_set_options }, { "get_output_data_size", decoder_get_output_data_size }, { NULL } }; ///////////////////////////////////////////////////////////////////////////// static struct PluginCodec_information licenseInfo = { 1143692893, // timestamp = Thu 30 Mar 2006 04:28:13 AM UTC "Craig Southeren, Post Increment", // source code author "1.0", // source code version "cr...@po...", // source code email "http://www.postincrement.com", // source code URL "Copyright (C) 2004 by Post Increment, All Rights Reserved", // source code copyright "MPL 1.0", // source code license PluginCodec_License_MPL, // source code license "VIC H.261", // codec description "", // codec author "", // codec version "", // codec email "", // codec URL "Copyright (c) 1994 Regents of the University of California", // codec copyright information NULL, // codec license PluginCodec_License_BSD // codec license code }; ///////////////////////////////////////////////////////////////////////////// static const char YUV420PDesc[] = { "YUV420P" }; static const char h261QCIFDesc[] = { "H.261-QCIF" }; static const char h261CIFDesc[] = { "H.261-CIF" }; static const char h261Desc[] = { "H.261" }; static const char sdpH261[] = { "h261" }; ///////////////////////////////////////////////////////////////////////////// static struct PluginCodec_Definition h261CodecDefn[6] = { { // H.323 CIF encoder PLUGIN_CODEC_VERSION_VIDEO, // codec API version &licenseInfo, // license information PluginCodec_MediaTypeVideo | // audio codec PluginCodec_RTPTypeExplicit, // specified RTP type h261CIFDesc, // text decription YUV420PDesc, // source format h261CIFDesc, // destination format 0, // user data H261_CLOCKRATE, // samples per second H261_BITRATE, // raw bits per second 20000, // nanoseconds per frame CIF_WIDTH, // frame width CIF_HEIGHT, // frame height 10, // recommended frame rate 60, // maximum frame rate RTP_RFC2032_PAYLOAD, // IANA RTP payload code NULL, // RTP payload name create_encoder, // create codec function destroy_encoder, // destroy codec codec_encoder, // encode/decode cifEncoderControls, // codec controls PluginCodec_H323VideoCodec_h261, // h323CapabilityType NULL // h323CapabilityData }, { // H.323 CIF decoder PLUGIN_CODEC_VERSION_VIDEO, // codec API version &licenseInfo, // license information PluginCodec_MediaTypeVideo | // audio codec PluginCodec_RTPTypeExplicit, // specified RTP type h261CIFDesc, // text decription h261CIFDesc, // source format YUV420PDesc, // destination format 0, // user data H261_CLOCKRATE, // samples per second H261_BITRATE, // raw bits per second 20000, // nanoseconds per frame CIF_WIDTH, // frame width CIF_HEIGHT, // frame height 10, // recommended frame rate 60, // maximum frame rate RTP_RFC2032_PAYLOAD, // IANA RTP payload code NULL, // RTP payload name create_decoder, // create codec function destroy_decoder, // destroy codec codec_decoder, // encode/decode cifDecoderControls, // codec controls PluginCodec_H323VideoCodec_h261, // h323CapabilityType NULL // h323CapabilityData }, { // H.323 QCIF encoder PLUGIN_CODEC_VERSION_VIDEO, // codec API version &licenseInfo, // license information PluginCodec_MediaTypeVideo | // audio codec PluginCodec_RTPTypeExplicit, // specified RTP type h261QCIFDesc, // text decription YUV420PDesc, // source format h261QCIFDesc, // destination format 0, // user data H261_CLOCKRATE, // samples per second H261_BITRATE, // raw bits per second 20000, // nanoseconds per frame QCIF_WIDTH, // frame width QCIF_HEIGHT, // frame height 10, // recommended frame rate 60, // maximum frame rate RTP_RFC2032_PAYLOAD, // IANA RTP payload code NULL, // RTP payload name create_encoder, // create codec function destroy_encoder, // destroy codec codec_encoder, // encode/decode qcifEncoderControls, // codec controls PluginCodec_H323VideoCodec_h261, // h323CapabilityType NULL // h323CapabilityData }, { // H.323 QCIF decoder PLUGIN_CODEC_VERSION_VIDEO, // codec API version &licenseInfo, // license information PluginCodec_MediaTypeVideo | // audio codec PluginCodec_RTPTypeExplicit, // specified RTP type h261QCIFDesc, // text decription h261QCIFDesc, // source format YUV420PDesc, // destination format 0, // user data H261_CLOCKRATE, // samples per second H261_BITRATE, // raw bits per second 20000, // nanoseconds per frame QCIF_WIDTH, // frame width QCIF_HEIGHT, // frame height 10, // recommended frame rate 60, // maximum frame rate RTP_RFC2032_PAYLOAD, // IANA RTP payload code NULL, // RTP payload name create_decoder, // create codec function destroy_decoder, // destroy codec codec_decoder, // encode/decode qcifDecoderControls, // codec controls PluginCodec_H323VideoCodec_h261, // h323CapabilityType NULL // h323CapabilityData }, { // SIP encoder PLUGIN_CODEC_VERSION_VIDEO, // codec API version &licenseInfo, // license information PluginCodec_MediaTypeVideo | // audio codec PluginCodec_RTPTypeExplicit, // specified RTP type h261Desc, // text decription YUV420PDesc, // source format h261Desc, // destination format 0, // user data H261_CLOCKRATE, // samples per second H261_BITRATE, // raw bits per second 20000, // nanoseconds per frame CIF_WIDTH, // frame width CIF_HEIGHT, // frame height 10, // recommended frame rate 60, // maximum frame rate RTP_RFC2032_PAYLOAD, // IANA RTP payload code sdpH261, // RTP payload name create_encoder, // create codec function destroy_encoder, // destroy codec codec_encoder, // encode/decode sipEncoderControls, // codec controls PluginCodec_H323Codec_NoH323, // h323CapabilityType NULL // h323CapabilityData }, { // SIP decoder PLUGIN_CODEC_VERSION_VIDEO, // codec API version &licenseInfo, // license information PluginCodec_MediaTypeVideo | // audio codec PluginCodec_RTPTypeExplicit, // specified RTP type h261Desc, // text decription h261Desc, // source format YUV420PDesc, // destination format 0, // user data H261_CLOCKRATE, // samples per second H261_BITRATE, // raw bits per second 20000, // nanoseconds per frame CIF_WIDTH, // frame width CIF_HEIGHT, // frame height 10, // recommended frame rate 60, // maximum frame rate RTP_RFC2032_PAYLOAD, // IANA RTP payload code sdpH261, // RTP payload name create_decoder, // create codec function destroy_decoder, // destroy codec codec_decoder, // encode/decode sipDecoderControls, // codec controls PluginCodec_H323Codec_NoH323, // h323CapabilityType NULL // h323CapabilityData }, }; #define NUM_DEFNS (sizeof(h261CodecDefn) / sizeof(struct PluginCodec_Definition)) ///////////////////////////////////////////////////////////////////////////// extern "C" { PLUGIN_CODEC_DLL_API struct PluginCodec_Definition * PLUGIN_CODEC_GET_CODEC_FN(unsigned * count, unsigned version) { if (version < PLUGIN_CODEC_VERSION_VIDEO) { *count = 0; return NULL; } else { *count = NUM_DEFNS; return h261CodecDefn; } } }; --- NEW FILE: h261vic.vcproj --- <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" Version="7.10" Name="h261vic" ProjectGUID="{E6897206-9765-4B73-9A98-DAC5787814CE}" SccProjectName="" SccLocalPath=""> <Platforms> <Platform Name="Win32"/> </Platforms> <Configurations> <Configuration Name="Release|Win32" OutputDirectory="..\..\Release" IntermediateDirectory="..\..\Release\GSM" ConfigurationType="2" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="FALSE" CharacterSet="2"> <Tool Name="VCCLCompilerTool" Optimization="2" InlineFunctionExpansion="1" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_CODEC_DLL_EXPORTS" StringPooling="TRUE" RuntimeLibrary="2" EnableFunctionLevelLinking="TRUE" RuntimeTypeInfo="TRUE" ProgramDataBaseFileName="$(IntDir)/$(TargetName).pdb" WarningLevel="3" SuppressStartupBanner="TRUE"/> <Tool Name="VCCustomBuildTool"/> <Tool Name="VCLinkerTool" IgnoreImportLibrary="TRUE" OutputFile="../../Release/h261vic_pwplugin.dll" LinkIncremental="1" SuppressStartupBanner="TRUE" ImportLibrary="$(IntDir)/$(TargetName).lib" TargetMachine="1"/> <Tool Name="VCMIDLTool" PreprocessorDefinitions="NDEBUG" MkTypLibCompatible="TRUE" SuppressStartupBanner="TRUE" TargetEnvironment="1" TypeLibraryName=".\..\Release/h261vic.tlb" HeaderFileName=""/> <Tool Name="VCPostBuildEventTool"/> <Tool Name="VCPreBuildEventTool"/> <Tool Name="VCPreLinkEventTool"/> <Tool Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="3081"/> <Tool Name="VCWebServiceProxyGeneratorTool"/> <Tool Name="VCXMLDataGeneratorTool"/> <Tool Name="VCWebDeploymentTool"/> <Tool Name="VCManagedWrapperGeneratorTool"/> <Tool Name="VCAuxiliaryManagedWrapperGeneratorTool"/> </Configuration> <Configuration Name="Debug|Win32" OutputDirectory="..\..\Debug" IntermediateDirectory="..\..\Debug\H261-vic" ConfigurationType="2" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="FALSE" CharacterSet="2"> <Tool Name="VCCLCompilerTool" Optimization="0" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_CODEC_DLL_EXPORTS" BasicRuntimeChecks="3" RuntimeLibrary="3" RuntimeTypeInfo="TRUE" ProgramDataBaseFileName="$(IntDir)/$(TargetName).pdb" WarningLevel="4" SuppressStartupBanner="TRUE" DebugInformationFormat="3"/> <Tool Name="VCCustomBuildTool"/> <Tool Name="VCLinkerTool" IgnoreImportLibrary="TRUE" AdditionalDependencies="wsock32.lib" OutputFile="../../Debug/h261vic_pwplugin.dll" LinkIncremental="1" SuppressStartupBanner="TRUE" GenerateDebugInformation="TRUE" ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb" ImportLibrary="$(IntDir)/$(TargetName).lib" TargetMachine="1"/> <Tool Name="VCMIDLTool" PreprocessorDefinitions="_DEBUG" MkTypLibCompatible="TRUE" SuppressStartupBanner="TRUE" TargetEnvironment="1" TypeLibraryName=".\..\Debug/h261vic.tlb" HeaderFileName=""/> <Tool Name="VCPostBuildEventTool"/> <Tool Name="VCPreBuildEventTool"/> <Tool Name="VCPreLinkEventTool"/> <Tool Name="VCResourceCompilerTool" PreprocessorDefinitions="_DEBUG" Culture="3081"/> <Tool Name="VCWebServiceProxyGeneratorTool"/> <Tool Name="VCXMLDataGeneratorTool"/> <Tool Name="VCWebDeploymentTool"/> <Tool Name="VCManagedWrapperGeneratorTool"/> <Tool Name="VCAuxiliaryManagedWrapperGeneratorTool"/> </Configuration> </Configurations> <References> </References> <Files> <Filter Name="Source Files" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> <File RelativePath=".\h261vic.cxx"> </File> </Filter> <Filter Name="VIC Files" Filter=".c"> <Filter Name="C Files" Filter=""> <File RelativePath=".\vic\bv.c"> </File> <File RelativePath=".\vic\huffcode.c"> </File> </Filter> <Filter Name="CXX Files" Filter=""> <File RelativePath=".\vic\dct.cxx"> </File> <File RelativePath=".\vic\encoder-h261.cxx"> </File> <File RelativePath=".\vic\p64.cxx"> </File> <File RelativePath=".\vic\p64encoder.cxx"> </File> <File RelativePath=".\vic\transmitter.cxx"> </File> <File RelativePath=".\vic\vid_coder.cxx"> </File> </Filter> <Filter Name="H Files" Filter=""> <File RelativePath=".\vic\bsd-endian.h"> </File> <File RelativePath=".\vic\config.h"> </File> <File RelativePath=".\vic\dct.h"> </File> <File RelativePath=".\vic\encoder-h261.h"> </File> <File RelativePath=".\vic\grabber.h"> </File> <File RelativePath=".\vic\p64-huff.h"> </File> <File RelativePath=".\vic\p64.h"> </File> <File RelativePath=".\vic\p64encoder.h"> </File> <File RelativePath=".\vic\transmitter.h"> </File> <File RelativePath=".\vic\vid_coder.h"> </File> </Filter> </Filter> </Files> <Globals> </Globals> </VisualStudioProject> |