[xiph-cvs] cvs commit: vorbis-plugins/realplayer/render/make linux-2.0-libc6-i386.mak

Jack Moffitt jack at xiph.org
Tue Jan 30 20:58:52 PST 2001



jack        01/01/30 20:58:52

  Added:       realplayer README
               realplayer/filefmt fvorbis.cpp fvorbis.h
               realplayer/filefmt/make linux-2.0-libc6-i386.mak
               realplayer/render fivemque.cpp fivemque.h rvorbis.cpp
                        rvorbis.h
               realplayer/render/make linux-2.0-libc6-i386.mak
  Log:
  first cut at a realplayer plugin

Revision  Changes    Path
1.1                  vorbis-plugins/realplayer/README

Index: README
===================================================================
You'll need the RMA SDK to compile these.  You can find it at
www.realnetworks.com in the DevZone.

These currently work but don't support chaining or seeking.  Also
only stereo 44.1kHz files are supported.

Streaming doesn't seem to work but should soon.

Since the RMA SDK is hard to find at realnetworks.com, you can find it here:
http://i.cantcode.com/~jack/rsg2sdk_r4.tar.gz

You can find RealPlayer8 at www.real.com or www.realnetworks.com, although
this plugin should work any g2 player i think.

jack.

1.1                  vorbis-plugins/realplayer/filefmt/fvorbis.cpp

Index: fvorbis.cpp
===================================================================
#define INITGUID

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>

#include "pntypes.h"
#include "pncom.h"
#include "rmacomm.h"
#include "rmapckts.h"
#include "rmaplugn.h"
#include "rmafiles.h"
#include "rmaformt.h"

#include "fvorbis.h"

// static variables
const char *CVorbisFileFormat::zm_pDescription = DESCRIPTION;
const char *CVorbisFileFormat::zm_pCopyright = COPYRIGHT;
const char *CVorbisFileFormat::zm_pMoreInfoURL = MORE_INFO_URL;
const char *CVorbisFileFormat::zm_pFileMimeTypes[] = FILE_MIME_TYPES;
const char *CVorbisFileFormat::zm_pFileExtensions[] = FILE_EXTENSIONS;
const char *CVorbisFileFormat::zm_pFileOpenNames[] = FILE_OPEN_NAMES;

int CVorbisFileFormat::instno = 0;

STDAPI RMACreateInstance(IUnknown **ppExFileFormatObj)
{
        //printf("RMACreateInstance() called\n");

        *ppExFileFormatObj = (IUnknown *)(IRMAPlugin *)new CVorbisFileFormat();
        if (*ppExFileFormatObj != NULL) {
                (*ppExFileFormatObj)->AddRef();
                return PNR_OK;	
        }

        return PNR_OUTOFMEMORY;
}

// constructor
CVorbisFileFormat::CVorbisFileFormat(void)
        :	m_RefCount(0),
                m_pClassFactory(NULL),
                m_pFileObj(NULL),
                m_pStatus(NULL),
                m_State(Ready),
                m_NextPacketDeliveryTime(0),
                m_ogg_inited(0)
{
        //printf("Entering CVorbisFileFormat()\n");
        m_instno = instno++;
        //printf("Exiting CVorbisFileFormat(%d)\n", m_instno);
}

STDMETHODIMP CVorbisFileFormat::GetPluginInfo(
        REF(BOOL) bLoadMultiple,
        REF(const char *) pDescription,
        REF(const char *) pCopyright,
        REF(const char *) pMoreInfoURL,
        REF(UINT32) versionNumber
)
{
        //printf("Entering GetPluginInfo(%d)\n", m_instno);

        // File Format plugins must be able to be multiply instantiated
        bLoadMultiple = TRUE;

        pDescription = zm_pDescription;
        pCopyright = zm_pCopyright;
        pMoreInfoURL = zm_pMoreInfoURL;
        versionNumber = PLUGIN_VERSION;

        //printf("Exiting GetPluginInfo(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::GetFileFormatInfo(
        REF(const char **) pFileMimeTypes,
        REF(const char **) pFileExtensions,
        REF(const char **) pFileOpenNames
)
{
        //printf("Entering GetFileFormatInfo(%d)\n", m_instno);

        pFileMimeTypes = zm_pFileMimeTypes;
        pFileExtensions = zm_pFileExtensions;
        pFileOpenNames = zm_pFileOpenNames;

        //printf("Exiting GetFileFormatInfo(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::InitPlugin(IUnknown *pRMACore)
{
        //printf("Entering InitPlugin(%d)\n", m_instno);
        
        // store a reference to the IRMACommonClassFactory interface
        pRMACore->QueryInterface(IID_IRMACommonClassFactory, (void **)&m_pClassFactory);
        if (m_pClassFactory == NULL) return PNR_NOTIMPL;

        // queryinterface adds a reference for us, we are responsible
        // for release the reference when we're done

        //printf("Exiting InitPlugin(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::InitFileFormat(
        IRMARequest *pRequest,
        IRMAFormatResponse *pFormatResponse,
        IRMAFileObject *pFileObject
)
{
        //printf("Entering InitFileFormat(%d)\n", m_instno);

        // the format response object is used to notify rma core of our status
        m_pStatus = pFormatResponse;
        if (m_pStatus != NULL)
                m_pStatus->AddRef();

        // the file object is used to handle file i/o
        m_pFileObj = pFileObject;
        if (m_pFileObj != NULL) {
                m_pFileObj->AddRef();

                // init and check file, then associate file with response object
                m_State = InitPending;
                m_pFileObj->Init(PN_FILE_READ | PN_FILE_BINARY, this);
        } 

        ogg_sync_init(&m_oy);
        vorbis_info_init(&m_initial_i);
        vorbis_comment_init(&m_initial_c);
        m_granulepos = 0;
        m_ogg_inited = 1;

        //printf("Exiting InitFileFormat(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::InitDone(PN_RESULT status)
{
        //printf("Entering InitDone(%d)\n", m_instno);

        if (m_State != InitPending) return PNR_UNEXPECTED;

        // notify RMA core that init started in InitFileFormat is done
        m_State = Ready;
        m_pStatus->InitDone(status);

        //printf("Exiting InitDone(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::GetFileHeader(void)
{
        IRMAFileStat *pFileStatObj;

        //printf("Entering GetFileHeader(%d)\n", m_instno);

        if (m_State != Ready) return PNR_UNEXPECTED;

        // async stuff makes this muddy, but here's the steps
        // 1) stat the file to get the length
        // 2) in StatDone, 

        m_State = GetFileHeaderStatPending;

        m_pFileObj->QueryInterface(IID_IRMAFileStat, (void **)&pFileStatObj);
        if (pFileStatObj != NULL) {
                pFileStatObj->Stat(this);
                pFileStatObj->Release();
        }

        //printf("Exiting GetFileHeader(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::StatDone(PN_RESULT status, UINT32 ulSize, UINT32 ulCreationTime, UINT32 ulAccessTime,
                                         UINT32 ulModificationTime, UINT32 ulMode)
{
        //printf("Entering StatDone(%d)\n", m_instno);

        if (m_State != GetFileHeaderStatPending) return PNR_UNEXPECTED;

        m_State = GFHInitialHeaderReadPending;

        m_FileSize = ulSize;

        //printf("Filesize of this ogg file is %ld\n", m_FileSize);

        m_pFileObj->Read(READ_LENGTH);

        //printf("Exiting StatDone(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::ReadDone(PN_RESULT status, IRMABuffer *pBuffer)
{
        char *buffer;
        ogg_page og;
        ogg_packet op;
        int result;
        int falling_through = 0;

        //printf("Enterint ReadDone(%d)\n", m_instno);
        
        switch (m_State) {
        case GFHInitialHeaderReadPending:
                //printf("state = GFHInitialHeadReadPending\n");
                if (pBuffer == NULL) {
                        m_State = Ready;
                        return PNR_INVALID_FILE;
                }

                // submit what we read to libvorbis
                buffer = ogg_sync_buffer(&m_oy, pBuffer->GetSize());
                memcpy(buffer, pBuffer->GetBuffer(), pBuffer->GetSize());
                ogg_sync_wrote(&m_oy, pBuffer->GetSize());

                //printf("GFHIHRP: submitted %d bytes to ogg\n", pBuffer->GetSize());

                // if we didn't read enough, read some more
                if (ogg_sync_pageout(&m_oy, &og) != 1) {
                        m_pFileObj->Read(READ_LENGTH);
                        return PNR_OK;
                }
                
                m_initial_serialno = ogg_page_serialno(&og);
                ogg_stream_init(&m_os, ogg_page_serialno(&og));

                //printf("serial number is %ld\n", m_initial_serialno);

                if (ogg_stream_pagein(&m_os, &og) < 0) {
                        //printf("GFHIHRP: ogg_stream_pagein failed...\n");
                        // error
                        m_State = Ready;
                        return PNR_INVALID_FILE;
                }

                if (ogg_stream_packetout(&m_os, &op) != 1) {
                        //printf("couldn't read initial packet\n");
                        // must not be vorbis
                        return PNR_INVALID_FILE;
                }

                if (vorbis_synthesis_headerin(&m_initial_i, &m_initial_c, &op) < 0) {
                        //printf("GFHIHRP: vorbis_synthesis headerin failed\n");
                        // error: not a vorbis header
                        m_State = Ready;
                        return PNR_INVALID_FILE;
                }

                // we're sure we're vorbis.  need to read the comments and the codebooks
                m_State = GFHInitialHeaderCommentReadPending;
                
                falling_through = 1;
                // pass through intentional
        case GFHInitialHeaderCommentReadPending:
                //printf("state = GFHInitialHeaderCommentReadPending\n");
                if (!falling_through) {
                        if (pBuffer == NULL) {
                                m_State = Ready;
                                return PNR_INVALID_FILE;
                        }

                        // submit what we read to libvorbis
                        buffer = ogg_sync_buffer(&m_oy, pBuffer->GetSize());
                        memcpy(buffer, pBuffer->GetBuffer(), pBuffer->GetSize());
                        ogg_sync_wrote(&m_oy, pBuffer->GetSize());			
                }

                if (ogg_sync_pageout(&m_oy, &og) != 1) {
                        // not enough data
                        m_pFileObj->Read(READ_LENGTH);
                        return PNR_OK;
                }
                
                //printf("GFHIHCRP: we got a page...\n");

                ogg_stream_pagein(&m_os, &og); // we can ignore these errors, they'll show up later
                
                result = ogg_stream_packetout(&m_os, &op);
                // do we need more data
                if (result == 0) {
                        m_pFileObj->Read(READ_LENGTH);
                        return PNR_OK;
                }

                // was there an error
                if (result < 0) {
                        m_State = Ready;
                        return PNR_INVALID_FILE;
                }

                vorbis_synthesis_headerin(&m_initial_i, &m_initial_c, &op);
                
                // got the comments 
                m_State = GFHInitialHeaderCodebookReadPending;
                
                falling_through = 1;
                // fall through intentional
        case GFHInitialHeaderCodebookReadPending:
                //printf("state = GFHInitialHeaderCodebookReadPending\n");

                if (!falling_through) {
                        if (pBuffer == NULL) {
                                m_State = Ready;
                                return PNR_INVALID_FILE;
                        }

                        // submit what we read to libvorbis
                        buffer = ogg_sync_buffer(&m_oy, pBuffer->GetSize());
                        memcpy(buffer, pBuffer->GetBuffer(), pBuffer->GetSize());
                        ogg_sync_wrote(&m_oy, pBuffer->GetSize());
                }

                if (ogg_sync_pageout(&m_oy, &og) != 1) {
                        // not enough data
                        m_pFileObj->Read(READ_LENGTH);
                        return PNR_OK;
                }

                ogg_stream_pagein(&m_os, &og);

                result = ogg_stream_packetout(&m_os, &op);
                // do we need more data?
                if (result == 0) {
                        m_pFileObj->Read(READ_LENGTH);
                        return PNR_OK;
                }

                // was there an error?
                if (result < 0) {
                        m_State = Ready;
                        return PNR_INVALID_FILE;
                }
                
                vorbis_synthesis_headerin(&m_initial_i, &m_initial_c, &op);

                // we know it's vorbis.  that's good enough. reset the stream state.
                ogg_stream_clear(&m_os);

                // and the sync state
                ogg_sync_reset(&m_oy);

                // now we need to seek to the end and see if we're the only logical stream
                m_State = GFHSeekEndPending;

                m_offset = m_FileSize;
                m_begin = m_FileSize;
                m_pFileObj->Seek(m_FileSize, FALSE);
                
                return PNR_OK;
        case GFHReadEndSearching:
                //printf("state = GFHReadEndSearching\n");
                // we're looking for a page

                // if we couldn't read anymore data, seek back some more.
                if (pBuffer == NULL) {
                        m_State = GFHSeekEndSearching;
                        
                        m_begin -= READ_LENGTH;
                        m_pFileObj->Seek(m_begin, FALSE);

                        return PNR_OK;
                }

                // add the new data
                buffer = ogg_sync_buffer(&m_oy, pBuffer->GetSize());
                memcpy(buffer, pBuffer->GetBuffer(), pBuffer->GetSize());
                ogg_sync_wrote(&m_oy, pBuffer->GetSize());

                if (ogg_sync_pageout(&m_oy, &og) != 1) {
                        // more data please
                        m_pFileObj->Read(READ_LENGTH);

                        return PNR_OK;
                }

                // yay we found a page

                // is there more than one logical bitstream?
                if (ogg_page_serialno(&og) != m_initial_serialno) {
                        // this is a chained bitstream
                        // this is NOT currently implemented.
                        m_State = Ready;
                        return PNR_INVALID_FILE;
                } else {
                        // now we can get the length of the song
                        m_FileTime = (UINT32)((float)(ogg_page_granulepos(&og) / m_initial_i.rate) * 1000.0);

                        m_State = GFHSeekBeginPending;
                        m_pFileObj->Seek(0, FALSE);

                        return PNR_OK;
                }

                break;
        case GetPacketReadPending:
                //printf("state = GetPacketReadPending\n");
                if (pBuffer == NULL) {
                        m_State = Ready;
                        return PNR_UNEXPECTED;
                }
                
                // send the data to the ogg layer
                buffer = ogg_sync_buffer(&m_oy, pBuffer->GetSize());
                memcpy(buffer, pBuffer->GetBuffer(), pBuffer->GetSize());
                ogg_sync_wrote(&m_oy, pBuffer->GetSize());

                // do we have a page yet?
                if (ogg_sync_pageout(&m_oy, &og) != 1) {
                        // get more data
                        m_pFileObj->Read(READ_LENGTH);
                        return PNR_OK;
                }

                CreatePacketObj(&og, m_granulepos);
                m_granulepos = ogg_page_granulepos(&og);

                return PNR_OK;
        default:
                return PNR_UNEXPECTED;
        }
        
        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::SeekDone(PN_RESULT status)
{
        //printf("Entering SeekDone(%d)\n", m_instno);

        switch (m_State) {
        case GFHSeekEndPending:
                //printf("state = GFHSeekEndPending\n");
                // now we need to read the last page in this file
                
                // start searching
                m_State = GFHSeekEndSearching;

                m_begin -= READ_LENGTH;
                m_pFileObj->Seek(m_begin, FALSE);

                return PNR_OK;
        case GFHSeekEndSearching:
                //printf("state = GFHSeekEndSearching\n");
                // find a page
                m_State = GFHReadEndSearching;

                m_pFileObj->Read(READ_LENGTH);
                
                return PNR_OK;
        case GFHSeekBeginPending:
                //printf("state = GFHSeekBeginPending\n");
                m_State = Ready;

                // let's reset the stream/sync states
                ogg_sync_reset(&m_oy);

                CreateFileHeaderObj();

                return PNR_OK;
        default:
                return PNR_UNEXPECTED;
        }

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::GetStreamHeader(UINT16 streamNo)
{
        //printf("Entering GetStreamHeader(%d)\n", m_instno);

        if (m_State != Ready) return PNR_UNEXPECTED;

        CreateStreamHeaderObj();

        //printf("Exiting GetStreamHeader(%d)\n", m_instno);

        return PNR_OK;
}

void CVorbisFileFormat::CreateFileHeaderObj(void)
{
        //printf("Entering CreateFileHeaderObj(%d)\n", m_instno);
        m_State = Ready;

        // Step 5: create new object containing header data
        IRMAValues *pHeaderObj = NULL;
        m_pClassFactory->CreateInstance(CLSID_IRMAValues, (void **)&pHeaderObj);
        
        if (pHeaderObj != NULL) {
                // required property: StreamCount
                pHeaderObj->SetPropertyULONG32("StreamCount", 1);

                // step 6: notify rma core that header object is ready
                m_pStatus->FileHeaderReady(PN_STATUS_OK, pHeaderObj);

                // release object since we're done with it
                pHeaderObj->Release();
        }

        //printf("Exiting CreateFileHeaderObj(%d)\n", m_instno);
}

void CVorbisFileFormat::CreateStreamHeaderObj(void)
{
        UINT32 avgBitRate;

        //printf("Entering CreateStreamHeaderObj(%d)\n", m_instno);

        m_State = Ready;

        IRMAValues *pStreamHeaderObj = NULL;
        m_pClassFactory->CreateInstance(CLSID_IRMAValues, (void **)&pStreamHeaderObj);

        if (pStreamHeaderObj != NULL) {
                // these properties are required

                // "StreamNumber" the stream number
                pStreamHeaderObj->SetPropertyULONG32("StreamNumber", STREAM_NO);

                // "AvgBitRate" the average bitrate of this stream
                avgBitRate = (UINT32)((float)((m_FileSize * 8) / (m_FileTime / 1000)));
                pStreamHeaderObj->SetPropertyULONG32("AvgBitRate", avgBitRate);
                //printf("AvgBitRate = %ld\n", avgBitRate);

                // preroll might not be required
                // "Preroll" the amount to prebuffer
                //pStreamHeaderObj->SetPropertyULONG32("Preroll", 0);

                // "Duration" length in milliseconds
                pStreamHeaderObj->SetPropertyULONG32("Duration", m_FileTime);
                //printf("Duration = %ld\n", m_FileTime);

                // "MimeType" the mime-type
                IRMABuffer *pStringObj = NULL;
                m_pClassFactory->CreateInstance(CLSID_IRMABuffer, (void **)&pStringObj);
                if (pStringObj != NULL) {
                        char *streamMimeType = STREAM_MIME_TYPE;
                        pStringObj->Set((const BYTE *)streamMimeType, strlen(streamMimeType) + 1);
                        pStreamHeaderObj->SetPropertyCString("MimeType", pStringObj);
                        pStringObj->Release();
                }

                // notify RMA core
                m_pStatus->StreamHeaderReady(PN_STATUS_OK, pStreamHeaderObj);

                // release the object
                pStreamHeaderObj->Release();
        }

        //printf("Exiting CreateStreamHeaderObj(%d)\n", m_instno);
}

STDMETHODIMP CVorbisFileFormat::GetPacket(UINT16 streamNo)
{
        //printf("Entering GetPacket(%d)\n", m_instno);

        if (m_State != Ready) return PNR_UNEXPECTED;

        m_State = GetPacketReadPending;

        m_pFileObj->Read(READ_LENGTH);

        //printf("Exiting GetPacket(%d)\n", m_instno);

        return PNR_OK;
}

void CVorbisFileFormat::CreatePacketObj(ogg_page *og, ogg_int64_t granulepos)
{
        char *buffer;

        //printf("Entering CreatePacketObj(%d)\n", m_instno);

        m_State = Ready;

        IRMAPacket *pPacketObj = NULL;
        m_pClassFactory->CreateInstance(CLSID_IRMAPacket, (void **)&pPacketObj);
        if (pPacketObj != NULL) {
                float deliveryTime = (float)granulepos / 44100.0 * 1000.0;
                UINT16 streamNo = 0;

                printf("granulepos = %lld  deliverytime = %f\n", granulepos, deliveryTime);

                IRMABuffer *pBuffer = NULL;
                m_pClassFactory->CreateInstance(CLSID_IRMABuffer, (void **)&pBuffer);
                if (pBuffer != NULL) {
                        pBuffer->SetSize(og->header_len + og->body_len);
                        buffer = (char *)pBuffer->GetBuffer();
                        memcpy(buffer, og->header, og->header_len);
                        memcpy(&buffer[og->header_len], og->body, og->body_len);

                        pPacketObj->Set(pBuffer, (UINT32)deliveryTime, streamNo, 0, 0);

                        m_pStatus->PacketReady(PN_STATUS_OK, pPacketObj);

                        pPacketObj->Release();
                } else {
                        printf("OH SHIT111!\n");
                }
        } else {
                printf("OH SHIT222!\n");
        }

        //printf("Exiting CreatePacketObj(%d)\n", m_instno);
}

STDMETHODIMP CVorbisFileFormat::Seek(UINT32 requestedTime)
{
        //printf("Entering Seek(%d)\n", m_instno);
        // not implemented

        //printf("Exiting Seek(%d)\n", m_instno);
        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::Close(void)
{
        //printf("Entering Close(%d)\n", m_instno);
        if (m_ogg_inited) {
                vorbis_comment_clear(&m_initial_c);
                vorbis_info_clear(&m_initial_i);
                ogg_sync_clear(&m_oy);
        }

        if (m_pFileObj != NULL) {
                m_pFileObj->Close();
                m_pFileObj->Release();
                m_pFileObj = NULL;
        }

        if (m_pStatus != NULL) {
                m_pStatus->Release();
                m_pStatus = NULL;
        }

        if (m_pClassFactory != NULL) {
                m_pClassFactory->Release();
                m_pClassFactory = NULL;
        }

        //printf("Exiting Close(%d)\n", m_instno);

        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::CloseDone(PN_RESULT result)
{
        //printf("CloseDone() not implemented\n");
        return PNR_OK;
}

STDMETHODIMP CVorbisFileFormat::WriteDone(PN_RESULT result)
{
        //printf("WriteDone() not implemented\n");
        return PNR_OK;
}

CVorbisFileFormat::~CVorbisFileFormat(void)
{
        //printf("Entering ~CVorbisFileFormat(%d)\n", m_instno);
        Close();
        //printf("Exiting ~CVorbisFileFormat(%d)\n", m_instno);
}

STDMETHODIMP_(UINT32) CVorbisFileFormat::AddRef(void)
{
        return InterlockedIncrement(&m_RefCount);
}

STDMETHODIMP_(UINT32) CVorbisFileFormat::Release(void)
{
        if (InterlockedDecrement(&m_RefCount) > 0)
                return m_RefCount;

        delete this;
        return 0;
}

STDMETHODIMP CVorbisFileFormat::QueryInterface(REFIID interfaceID, void **ppInterfaceObj)
{
        if (IsEqualIID(interfaceID, IID_IUnknown)) {
                AddRef();
                *ppInterfaceObj = (IUnknown *)(IRMAPlugin *)this;
                return PNR_OK;
        } else if (IsEqualIID(interfaceID, IID_IRMAPlugin)) {
                AddRef();
                *ppInterfaceObj = (IRMAPlugin *)this;
                return PNR_OK;
        } else if (IsEqualIID(interfaceID, IID_IRMAFileResponse)) {
                AddRef();
                *ppInterfaceObj = (IRMAFileResponse *)this;
                return PNR_OK;
        } else if (IsEqualIID(interfaceID, IID_IRMAFileFormatObject)) {
                AddRef();
                *ppInterfaceObj = (IRMAFileFormatObject *)this;
                return PNR_OK;
        } else if (IsEqualIID(interfaceID, IID_IRMAFileStatResponse)) {
                AddRef();
                *ppInterfaceObj = (IRMAFileStatResponse *)this;
                return PNR_OK;
        }

        *ppInterfaceObj = NULL;
        return PNR_NOINTERFACE;
}

1.1                  vorbis-plugins/realplayer/filefmt/fvorbis.h

Index: fvorbis.h
===================================================================
#ifndef __FVORBIS_H__
#define __FVORBIS_H__

#define PLUGIN_VERSION 0
#define DESCRIPTION "Ogg Vorbis File Format Plugin"
#define COPYRIGHT "(c) 2001 Xiphophorus, All rights reserved."
#define MORE_INFO_URL "http://www.xiph.org"
#define FILE_MIME_TYPES {"application/x-ogg", NULL}
#define FILE_EXTENSIONS {"ogg", NULL}
#define FILE_OPEN_NAMES {"Ogg Vorbis (*.ogg)", NULL}
#define STREAM_NO 0
#define STREAM_MIME_TYPE "application/x-ogg"
#define READ_LENGTH 4096

typedef enum
{
        Ready,
        InitPending,
        GetFileHeaderStatPending,

        GFHInitialHeaderReadPending,
        GFHInitialHeaderCommentReadPending,
        GFHInitialHeaderCodebookReadPending,

        GFHSeekEndPending,
        GFHSeekEndSearching,
        GFHReadEndSearching,
        GFHSeekBeginPending,

        GetPacketSeekPending,
        GetPacketReadPending,
        SeekSeekPending
} PluginState;

class CVorbisFileFormat :	public IRMAFileFormatObject,
                                public IRMAFileResponse,
                                public IRMAFileStatResponse,
                                public IRMAPlugin
{
        public:

        CVorbisFileFormat(void);

        // IRMAFileFormatObject interface
        STDMETHOD(GetFileFormatInfo)
                (THIS_
                        REF(const char **)pFileMimeTypes,
                        REF(const char **)pFileExtensions,
                        REF(const char **)pFileOpenNames
                );

        STDMETHOD(InitFileFormat)
                (THIS_
                        IRMARequest *pRequest,
                        IRMAFormatResponse *pFormatResponse,
                        IRMAFileObject *pFileObject
                );

        STDMETHOD(GetFileHeader) (THIS);
        STDMETHOD(GetStreamHeader) (THIS_ UINT16 streamNo);
        STDMETHOD(GetPacket) (THIS_ UINT16 streamNo);
        STDMETHOD(Seek) (THIS_ UINT32 requestedTime);
        STDMETHOD(Close) (THIS);

        // IRMAFileResponse Interface
        STDMETHOD(InitDone) (THIS_ PN_RESULT status);
        STDMETHOD(SeekDone) (THIS_ PN_RESULT status);
        STDMETHOD(ReadDone) (THIS_ PN_RESULT status, IRMABuffer *pBuffer);
        STDMETHOD(WriteDone) (THIS_ PN_RESULT status);
        STDMETHOD(CloseDone) (THIS_ PN_RESULT status);

        // IRMAFileStatResponse Interface
        STDMETHOD(StatDone) 
                (THIS_ 
                        PN_RESULT status, 
                        UINT32 ulSize, 
                        UINT32 ulCreationTime, 
                        UINT32 ulAccessTime, 
                        UINT32 ulModificationTime,
                        UINT32 ulMode
                 );

        // IRMAPlugin Interface
        STDMETHOD(GetPluginInfo)
                (THIS_
                        REF(BOOL) bLoadMultiple,
                        REF(const char *) pDescription,
                        REF(const char *) pCopyright,
                        REF(const char *) pMoreInfoURL,
                        REF(UINT32) versionNumber
                );

        STDMETHOD(InitPlugin) (THIS_ IUnknown *pRMACore);

        // IUnknown COM Interface
        STDMETHOD(QueryInterface) (THIS_ REFIID ID, void **ppInterfaceObj);
        STDMETHOD_(UINT32, AddRef) (THIS);
        STDMETHOD_(UINT32, Release) (THIS);

        private:

        // private class variables
        UINT32 m_FileTime;      // total time of the file in milliseconds
        UINT32 m_FileSize;      // file size of the current file
        INT32 m_RefCount;	// Objects reference count
        IRMACommonClassFactory *m_pClassFactory; // creates common RMA classes
        IRMAFileObject *m_pFileObj;	// Used for file i/o
        IRMAFormatResponse *m_pStatus;	// Reports status to RMA core
        PluginState m_State;	// Status used for async calls
        UINT32 m_NextPacketDeliveryTime;	// Delivery time of next packet

        // ogg vorbis stuff
        int m_ogg_inited;
        ogg_int64_t m_granulepos;
        ogg_int64_t m_offset;
        ogg_int64_t m_begin;
        long m_initial_serialno;
        ogg_sync_state m_oy;

        //int m_links;
        //ogg_int64_t *m_offsets;
        //ogg_int64_t *m_dataoffsets;
        //long *m_serialnos;
        //ogg_int64_t *m_pcmlengths;
        //vorbis_info *m_vi;
        //vorbis_comment *m_vc;
        vorbis_info m_initial_i;
        vorbis_comment m_initial_c;

        // vorbis working state
        //ogg_int64_t m_pcmoffset;
        //long m_current_serialno;
        //int m_current_link;

        ogg_stream_state m_os;

        // private static class variables
        int m_instno;
        static int instno;
        static const char *zm_pDescription;
        static const char *zm_pCopyright;
        static const char *zm_pMoreInfoURL;
        static const char *zm_pFileMimeTypes[];
        static const char *zm_pFileExtensions[];
        static const char *zm_pFileOpenNames[];

        // private class methods
        ~CVorbisFileFormat(void);
        void CreateFileHeaderObj(void);
        void CreateStreamHeaderObj(void);
        void CreatePacketObj(ogg_page *og, ogg_int64_t granulepos);

        PRIVATE_DESTRUCTORS_ARE_NOT_A_CRIME
};

#endif  // __FVORBIS_H__

1.1                  vorbis-plugins/realplayer/filefmt/make/linux-2.0-libc6-i386.mak

Index: linux-2.0-libc6-i386.mak
===================================================================
# UMAKE generated Makefile
# build choices: default,release
# platform: linux-2.0-libc6-i386
# Wed Feb  2 15:36:22 2000
.SUFFIXES: .cpp .so
.c.so:
        $(CC) $(CCFLAGS) -fPIC -DPIC -o  $@ -c $<
.cpp.so:
        $(CXX) $(CXXFLAGS) -fPIC -DPIC -o  $@ -c $<

RM = rm -f
RM_DIR = rm -rf
MAKE_DEP = makedep.py
MAKE_DEP_FLAGS =   $(INCLUDES) $(DEFINES)
MAKE_LIB = ar cr 
MAKE_LIB_FLAGS =  
RANLIB = ranlib
CP = cp
MAKE = make

# Compilers
CC = gcc
CCFLAGS = -Wall -pipe -O2  $(INCLUDES) $(DEFINES)
CXX = g++
CXXFLAGS = -Wall -pipe -O2  $(INCLUDES) $(DEFINES)

# Linker
LD = g++
LDFLAGS = -shared -L/usr/X11R6/lib -L/usr/X11R6/lib 

DEPLIBS = 

DYNAMIC_LIBS = -logg -lvorbis

SRCS = \
        ../fvorbis.cpp

OBJS = $(COMPILED_OBJS) $(SOURCE_OBJS)

COMPILED_OBJS = \
        rel/obj/fvorbis.so

SOURCE_OBJS = 

INCLUDES = \
        -I/usr/X11R6/include \
        -I/usr/X11R6/include \
        -I/home/jack/download/rmasdk_6_0/include \
        -I.. \
        -I./pub

DEFINES = \
        -D_LINUX \
        -D_REENTRANT \
        -D_UNIX \
        -D_RED_HAT_5_X_

SYSLIBS = 

LOCAL_LIBS = 

rel/fvorbis.so : rel/obj $(OBJS) $(DEPLIBS)
        if test -d rel; then echo; else mkdir rel; fi
        $(LD) $(LDFLAGS) -o rel/fvorbis.so $(OBJS) $(DYNAMIC_LIBS) $(DEPLIBS) $(LOCAL_LIBS) $(SYSLIBS) -lgcc

clean::
        $(RM) rel/fvorbis.so $(COMPILED_OBJS)

## OBJECT DEPENDANCIES
rel/obj:
        if test -d rel; then echo; else mkdir rel; fi
        if test -d rel/obj; then echo; else mkdir rel/obj; fi
rel/obj/fvorbis.so : ../fvorbis.cpp
        $(CXX) $(CXXFLAGS) -fPIC -DPIC -o rel/obj/fvorbis.so -c ../fvorbis.cpp
copy:
        if test -d ../release; then echo; else mkdir ../release; fi
        cp rel/fvorbis.so ../release/fvorbis.so
depend:
        $(MAKE_DEP) $(MAKE_DEP_FLAGS) rel/obj/ $(SRCS)

1.1                  vorbis-plugins/realplayer/render/fivemque.cpp

Index: fivemque.cpp
===================================================================
/****************************************************************************
 * 
 *  $Id: fivemque.cpp,v 1.1 2001/01/31 04:58:50 jack Exp $
 *  
 *  Copyright (C) 1995,1996,1997 RealNetworks.
 *  All rights reserved.
 *  
 *  http://www.real.com/devzone
 *
 *  This program contains proprietary information of RealNetworks, Inc.,
 *  and is licensed subject to restrictions on use and distribution.
 *
 *  Very basic queue class.
 *
 */

/****************************************************************************
 * Includes
 */
#include <string.h>
#include "pntypes.h"
#include "fivemque.h"

/****************************************************************************
 *  FiveMinuteQueue::Add                                     ref:  fivemque.h
 *
 */
void
FiveMinuteQueue::Add(void* pElement)
{
    FiveMinuteElement*  pElem = new FiveMinuteElement(pElement);

    FiveMinuteElement*  pPtr;
    FiveMinuteElement** ppPtr;

    for (ppPtr = &m_pElemList; (pPtr = *ppPtr) != 0; ppPtr = &pPtr->m_pNext)
        ;

    *ppPtr = pElem;
}

/****************************************************************************
 *  FiveMinuteQueue::Remove                                  ref:  fivemque.h
 *
 */
void*
FiveMinuteQueue::Remove()
{
    if (!m_pElemList)
        return 0;

    FiveMinuteElement* pElem = m_pElemList;
    void* pPtr = pElem->m_pPtr;

    m_pElemList = m_pElemList->m_pNext;

    delete pElem;

    return pPtr;
}

1.1                  vorbis-plugins/realplayer/render/fivemque.h

Index: fivemque.h
===================================================================
/****************************************************************************
 * 
 *  $Id: fivemque.h,v 1.1 2001/01/31 04:58:50 jack Exp $
 *  
 *  Copyright (C) 1995,1996,1997 RealNetworks, Inc.
 *  All rights reserved.
 *  
 *  http://www.real.com/devzone
 *
 *  This program contains proprietary information of RealNetworks, Inc.,
 *  and is licensed subject to restrictions on use and distribution.
 *
 *  Very basic queue class.
 *
 */
#ifndef _FIVEMQUE_H_
#define _FIVEMQUE_H_

#ifndef _PNTYPES_H_
    #error FiveMinuteQueue assumes pntypes.h.
#endif

/****************************************************************************
 *
 *  FiveMinuteElement Class
 *
 */
class FiveMinuteElement
{
    friend		class FiveMinuteQueue;

    public:
    FiveMinuteElement(void* pPtr)
    {
        m_pPtr = pPtr;
        m_pNext = 0;
    };

    
    private:
    void*		m_pPtr;
    FiveMinuteElement*	m_pNext;

};

/****************************************************************************
 *
 *  FiveMinuteQueue Class
 *
 */
class FiveMinuteQueue
{
    public:
    FiveMinuteQueue()
        : m_pElemList(NULL)
        {};

    void  Add(void* pElement);
    void* Remove();

    
    private:
    FiveMinuteElement*  m_pElemList;

};

#endif /* _FIVEMQUE_H_ */

1.1                  vorbis-plugins/realplayer/render/rvorbis.cpp

Index: rvorbis.cpp
===================================================================
#define INITGUID

#include <stdio.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>

#include "pntypes.h"
#include "pncom.h"
#include "rmacore.h"
#include "rmacomm.h"
#include "rmapckts.h"
#include "rmaplugn.h"
#include "rmarendr.h"
#include "rmaausvc.h"

#include "fivemque.h"
#include "rvorbis.h"

STDAPI RMACreateInstance(IUnknown **ppRendererObj)
{
        *ppRendererObj = (IUnknown *)(IRMAPlugin *)new CVorbisRenderer();
        if (*ppRendererObj != NULL) {
                (*ppRendererObj)->AddRef();
                return PNR_OK;
        }

        return PNR_OUTOFMEMORY;
}

const char *CVorbisRenderer::zm_pDescription = DESCRIPTION;
const char *CVorbisRenderer::zm_pCopyright = COPYRIGHT;
const char *CVorbisRenderer::zm_pMoreInfoURL = MORE_INFO_URL;
const char *CVorbisRenderer::zm_pStreamMimeTypes[] = STREAM_MIME_TYPES;

CVorbisRenderer::CVorbisRenderer(void)
        : m_RefCount(0),
          m_pClassFactory(NULL),
          m_bInSeekMode(FALSE),
          m_bIsGapInStreaming(TRUE),
          m_oldRealTime(0),
          m_totalSamples(0)
{
}

STDMETHODIMP CVorbisRenderer::GetPluginInfo(
        REF(BOOL) bLoadMultiple,
        REF(const char *) pDescription,
        REF(const char *) pCopyright,
        REF(const char *) pMoreInfoURL,
        REF(UINT32) versionNumber
)
{
        bLoadMultiple = TRUE;
        pDescription = zm_pDescription;
        pCopyright = zm_pCopyright;
        pMoreInfoURL = zm_pMoreInfoURL;
        versionNumber = PLUGIN_VERSION;

        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::GetRendererInfo(
        REF(const char **) pStreamMimeTypes,
        REF(UINT32) initialGranularity
)
{
        pStreamMimeTypes = zm_pStreamMimeTypes;
        initialGranularity = TIME_SYNC_FREQ;

        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::InitPlugin(IUnknown *pRMACore)
{
        pRMACore->QueryInterface(IID_IRMACommonClassFactory, (void **)&m_pClassFactory);
        if (m_pClassFactory == NULL)
                return PNR_NOTIMPL;

        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::StartStream(IRMAStream *pStream, IRMAPlayer *pPlayer)
{
        m_OggState = OggInitialHeader;

        ogg_sync_init(&m_oy);

        m_pStream = pStream;
        m_pPlayer = pPlayer;

        if (m_pStream) m_pStream->AddRef();
        if (m_pPlayer) m_pPlayer->AddRef();

        // get interface to audio player
        if (PNR_OK != m_pPlayer->QueryInterface(IID_IRMAAudioPlayer, (void **)&m_pAudioPlayer))
                return !PNR_OK;

        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnHeader(IRMAValues *pStreamHeaderObj)
{
        m_audioFmt.uChannels = 2;
        m_audioFmt.uBitsPerSample = 16;
        m_audioFmt.ulSamplesPerSec = 44100;
        m_audioFmt.uMaxBlockSize = 4096;
        
        m_pAudioPlayer->CreateAudioStream(&m_pAudioStream);
        m_pAudioStream->Init(&m_audioFmt, pStreamHeaderObj);

        m_pAudioStream->AddDryNotification(this);

        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnBegin(UINT32 timeAfterBeing)
{
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::GetDisplayType(
        REF(RMA_DISPLAY_TYPE) displayType,
        REF(IRMABuffer *) pDisplayInfo
)
{
        displayType = RMA_DISPLAY_NONE;
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnPacket(IRMAPacket *pPacketObj, INT32 streamOffsetTime)
{
        char *buffer;
        ogg_page og;
        ogg_packet op;
        int result;
        int falling_through = 0;

        // ignore pre-seek packets
        if (m_bInSeekMode) return PNR_OK;

        // did we get a valid packet?
        if (pPacketObj->IsLost()) {
                printf("Lost a packet????\n");
                m_bIsGapInStreaming = TRUE;
                return PNR_OK;
        }

        LONG32 lRealTime = pPacketObj->GetTime();
        if (streamOffsetTime > lRealTime)
                lRealTime = 0;
        else
//		lRealTime -= streamOffsetTime;
                ;

        printf("streamoffsettime = %d\n", streamOffsetTime);

        // now correct m_oldRealTime
        m_oldRealTime = lRealTime;

        IRMABuffer *pPacketBuff = pPacketObj->GetBuffer();
        if (pPacketBuff != NULL) {
                UCHAR *pPacketData = pPacketBuff->GetBuffer();
                if (pPacketData != NULL) {
                        //printf("RENDER: decoding ogg page\n");
                        // submit packet to ogg layer
                        buffer = ogg_sync_buffer(&m_oy, pPacketBuff->GetSize());
                        memcpy(buffer, pPacketData, pPacketBuff->GetSize());
                        ogg_sync_wrote(&m_oy, pPacketBuff->GetSize());
                        
                        if (ogg_sync_pageout(&m_oy, &og) != 1) {
                                // not enough data yet
                                pPacketBuff->Release();
                                return PNR_OK;
                        }

                        switch (m_OggState) {
                        case OggInitialHeader:
                                ogg_stream_init(&m_os, ogg_page_serialno(&og));
                                vorbis_info_init(&m_vi);
                                vorbis_comment_init(&m_vc);
                                if (ogg_stream_pagein(&m_os, &og) < 0) {
                                        pPacketBuff->Release();
                                        return PNR_UNEXPECTED;
                                }
                                if (ogg_stream_packetout(&m_os, &op) != 1) {
                                        pPacketBuff->Release();
                                        return PNR_UNEXPECTED;
                                }
                                if (vorbis_synthesis_headerin(&m_vi, &m_vc, &op) < 0) {
                                        pPacketBuff->Release();
                                        return PNR_UNEXPECTED;
                                }
                                m_OggState = OggCommentHeader;
                                
                                printf("Got Initial Header\n");

                                falling_through = 1;
                                // fall through intentional
                        case OggCommentHeader:
                                if (!falling_through) {
                                        ogg_stream_pagein(&m_os, &og);
                                }
                                result = ogg_stream_packetout(&m_os, &op);
                                if (result < 0) {
                                        pPacketBuff->Release();
                                        return PNR_UNEXPECTED;
                                }
                                // need more data?
                                if (result == 0) break;
                                vorbis_synthesis_headerin(&m_vi, &m_vc, &op);
                                m_OggState = OggCodebookHeader;
                                
                                printf("Got Comment Header\n");

                                falling_through = 1;
                                // fall through intentional
                        case OggCodebookHeader:
                                if (!falling_through) {
                                        ogg_stream_pagein(&m_os, &og);
                                }
                                result = ogg_stream_packetout(&m_os, &op);
                                if (result < 0) {
                                        pPacketBuff->Release();
                                        return PNR_UNEXPECTED;
                                }
                                // need more data
                                if (result == 0) break;
                                vorbis_synthesis_headerin(&m_vi, &m_vc, &op);
                                vorbis_synthesis_init(&m_vd, &m_vi);
                                vorbis_block_init(&m_vd, &m_vb);

                                m_OggState = OggPlay;

                                printf("Got Codebooks\n");

                                falling_through = 1;
                                // fall through intentional
                        case OggPlay:
                                if (!falling_through) {
                                        ogg_stream_pagein(&m_os, &og);
                                }

                                printf("OGG PAGE CAME IN\n");
                                while (ogg_stream_packetout(&m_os, &op) > 0) {
                                        // we have a packet to decode
                                        float **pcm;
                                        int samples;
                                        int convsize;
                                        ogg_int16_t convbuffer[4096];

                                        convsize = 4096 / m_vi.channels;
                                        if (vorbis_synthesis(&m_vb, &op) == 0)
                                                vorbis_synthesis_blockin(&m_vd, &m_vb);
                                        else
                                                printf("ERROR ? HMMMMMMM\n");

                                        //printf("got a packet, get some samples\n");
                                        while ((samples = vorbis_synthesis_pcmout(&m_vd, &pcm)) > 0) {
                                                int i, j;
                                                int clipflag = 0;
                                                int bout = (samples < convsize ? samples : convsize);
                                                
                                                // convert floats to 16bit signed ints (host order) and interleave
                                                for (i = 0; i < m_vi.channels; i++) {
                                                        ogg_int16_t *ptr = convbuffer + i;
                                                        float *mono = pcm[i];
                                                        
                                                        for (j = 0; j < bout; j++) {
                                                                int val = mono[j] * 32767.f;
                                                                // guard against clipping
                                                                if (val > 32767) {
                                                                        val = 32767;
                                                                        clipflag = 1;
                                                                }
                                                                if (val < -32768) {
                                                                        val = -32768;
                                                                        clipflag = 1;
                                                                }
                                                                *ptr = val;
                                                                ptr += 2;
                                                        }
                                                }
                                                
                                                
                                                // send to audio output
                                                IRMABuffer *pBuffer = NULL;
                                                char *tmp;
                                                // create and fill a buffer
                                                m_pClassFactory->CreateInstance(CLSID_IRMABuffer, (void **)&pBuffer);
                                                if (pBuffer == NULL) {
                                                        printf("ERROR - no memory?\n");
                                                        return PNR_OUTOFMEMORY;
                                                }
                                                
                                                pBuffer->SetSize(bout * m_vi.channels * 2);
                                                tmp = (char *)pBuffer->GetBuffer();
                                                memcpy(tmp, convbuffer, bout * m_vi.channels * 2);
                                                
                                                m_oldRealTime = CalcMs(m_totalSamples * 4);
                                                m_totalSamples += bout;

                                                RMAAudioData *pAudioData = new RMAAudioData;
                                                pAudioData->pData = pBuffer;
                                                pAudioData->ulAudioTime = m_oldRealTime;

                                                printf("Sending %d samples (%ld ms) time = %d to audio out\n", bout, CalcMs(bout*4), m_oldRealTime);
                                                //m_oldRealTime += CalcMs(bout * 4);
                                                
                                                if (m_bIsGapInStreaming) {
                                                        pAudioData->uAudioStreamType = TIMED_AUDIO;
                                                        m_bIsGapInStreaming = FALSE;
                                                } else {
                                                        pAudioData->uAudioStreamType = STREAMING_AUDIO;
                                                }
                                                
                                                m_PacketQueue.Add((void *)pAudioData);
                                                //m_pAudioStream->Write(pAudioData);
                                                //pAudioData->pData->Release();
                                                //delete pAudioData;
                                                
                                                // tell vorbis how many samples we consumed
                                                vorbis_synthesis_read(&m_vd, bout);
                                        }
                                        //printf("done decoding packet\n");
                                }
                                //m_oldRealTime = lRealTime;
                                printf("old/real - %d/%d\n", m_oldRealTime, lRealTime);
                                printf("OGG PAGE DONE\n");
                                break;
                        default:
                                break;
                        }
                }

                pPacketBuff->Release();
        }

        return PNR_OK;
}

UINT32 CVorbisRenderer::CalcMs(UINT32 ulNumBytes)
{
        return ((UINT32)((1000.0 / (m_audioFmt.uChannels * ((m_audioFmt.uBitsPerSample == 8) ? 1 : 2)
                                    * m_audioFmt.ulSamplesPerSec)) * ulNumBytes));
}

STDMETHODIMP CVorbisRenderer::OnDryNotification(UINT32 ulCurrentStreamTime, UINT32 ulMinimumDurationRequired)
{
        UINT32 ulNumMsWritten = 0;

        RMAAudioData *pAudioData = (RMAAudioData *)m_PacketQueue.Remove();
        while (pAudioData) {
                m_pAudioStream->Write(pAudioData);
                
                ulNumMsWritten += CalcMs(pAudioData->pData->GetSize());

                pAudioData->pData->Release();
                delete pAudioData;

                if (ulNumMsWritten >= ulMinimumDurationRequired) break;

                pAudioData = (RMAAudioData *)m_PacketQueue.Remove();
        }

        printf("needed %ldms sent %ldms...\n", ulMinimumDurationRequired, ulNumMsWritten);
        
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnTimeSync(UINT32 currentPlayBackTime)
{
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnPreSeek(UINT32 timeBeforeSeek, UINT32 timeAfterSeek)
{
        m_bInSeekMode = TRUE;
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnPostSeek(UINT32 timeBeforeSeek, UINT32 timeAfterSeek)
{
        m_bInSeekMode = FALSE;
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnPause(UINT32 timeBeforePause)
{
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnBuffering(UINT32 reason, UINT16 percentComplete)
{
        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::OnEndofPackets(void)
{
        vorbis_comment_clear(&m_vc);
        vorbis_info_clear(&m_vi);
        ogg_stream_clear(&m_os);
        ogg_sync_clear(&m_oy);

        return PNR_OK;
}

STDMETHODIMP CVorbisRenderer::EndStream(void)
{
        if (m_pClassFactory != NULL) {
                m_pClassFactory->Release();
                m_pClassFactory = NULL;
        }
        
        return PNR_OK;
}

CVorbisRenderer::~CVorbisRenderer(void)
{
        EndStream();
}

STDMETHODIMP_(UINT32) CVorbisRenderer::AddRef(void)
{
        return InterlockedIncrement(&m_RefCount);
}

STDMETHODIMP_(UINT32) CVorbisRenderer::Release(void)
{
        if (InterlockedDecrement(&m_RefCount) > 0)
                return m_RefCount;

        delete this;
        return 0;
}

STDMETHODIMP CVorbisRenderer::QueryInterface(REFIID interfaceID, void **ppInterfaceObj)
{
        if (IsEqualIID(interfaceID, IID_IUnknown)) {
                AddRef();
                *ppInterfaceObj = (IUnknown *)(IRMAPlugin *)this;
                return PNR_OK;
        } else if (IsEqualIID(interfaceID, IID_IRMAPlugin)) {
                AddRef();
                *ppInterfaceObj = (IRMAPlugin *)this;
                return PNR_OK;
        } else if (IsEqualIID(interfaceID, IID_IRMARenderer)) {
                AddRef();
                *ppInterfaceObj = (IRMARenderer *)this;
                return PNR_OK;
        }

        *ppInterfaceObj = NULL;
        return PNR_NOINTERFACE;
}

1.1                  vorbis-plugins/realplayer/render/rvorbis.h

Index: rvorbis.h
===================================================================
#ifndef __RVORBIS_H__
#define __RVORBIS_H__

#define PLUGIN_VERSION 0
#define DESCRIPTION "Ogg Vorbis Renderer Plugin"
#define COPYRIGHT "(c) 2001 Xiphophorus, All Rights Reserved"
#define MORE_INFO_URL "http://www.xiph.org"
#define STREAM_MIME_TYPES { "application/x-ogg", NULL }
#define TIME_SYNC_FREQ 100

typedef enum
{
        OggInitialHeader,
        OggCommentHeader,
        OggCodebookHeader,
        OggPlay
} OggState;

class CVorbisRenderer: public IRMARenderer,
                       public IRMAPlugin,
                       public IRMADryNotification
{
 public:
        CVorbisRenderer(void);

        STDMETHOD(StartStream) (THIS_ IRMAStream *pStream, IRMAPlayer *pPlayer);
        STDMETHOD(EndStream) (THIS);
        STDMETHOD(OnHeader) (THIS_ IRMAValues *pStreamHeaderObj);
        STDMETHOD(OnPacket) (THIS_ IRMAPacket *pPacketObj, INT32 timeOffset);
        STDMETHOD(OnTimeSync) (THIS_ UINT32 currentPlayBackTime);
        STDMETHOD(OnPreSeek) (THIS_ UINT32 timeBefore, UINT32 timeAfter);
        STDMETHOD(OnPostSeek) (THIS_ UINT32 timeBefore, UINT32 timeAfter);
        STDMETHOD(OnPause) (THIS_ UINT32 timeBeforePause);
        STDMETHOD(OnBegin) (THIS_ UINT32 timeAfterBegin);
        STDMETHOD(OnBuffering) (THIS_ UINT32 reason, UINT16 percentComplete);
        STDMETHOD(GetRendererInfo)
                (THIS_
                 REF(const char **) pStreamMimeTypes,
                 REF(UINT32) initialGranularity
                );
        STDMETHOD(GetDisplayType)
                (THIS_
                 REF(RMA_DISPLAY_TYPE) displayType,
                 REF(IRMABuffer *) pDisplayInfo
                );
        STDMETHOD(OnEndofPackets) (THIS);

        STDMETHOD(GetPluginInfo)
                (THIS_
                 REF(BOOL) bLoadMultiple,
                 REF(const char *) pDescription,
                 REF(const char *) pCopyright,
                 REF(const char *) pMoreInfoURL,
                 REF(UINT32) versionNumber
                );
        STDMETHOD(InitPlugin) (THIS_ IUnknown *pRMACore);

        // IRMADryNotification Interface
        STDMETHOD(OnDryNotification)
                (THIS_
                 UINT32 ulCurrentStreamTime,
                 UINT32 ulMinimumDurationRequired
                );

        STDMETHOD(QueryInterface) (THIS_ REFIID interfaceID, void **ppInterfaceObj);
        STDMETHOD_(UINT32, AddRef) (THIS);
        STDMETHOD_(UINT32, Release) (THIS);

 private:

        UINT32 CalcMs(UINT32 ulNumBytes);
        ~CVorbisRenderer(void);

        INT32 m_RefCount;
        IRMACommonClassFactory *m_pClassFactory;
        BOOL m_bInSeekMode;
        BOOL m_bIsGapInStreaming;

        // vorbis decoding
        OggState m_OggState;
        ogg_sync_state m_oy;
        ogg_stream_state m_os;
        vorbis_info m_vi;
        vorbis_comment m_vc;
        vorbis_dsp_state m_vd;
        vorbis_block m_vb;

        // more stuff
        ogg_int64_t m_totalSamples;
        UINT32 m_oldRealTime;
        IRMAStream *m_pStream;
        IRMAPlayer *m_pPlayer;
        IRMAAudioPlayer *m_pAudioPlayer;
        IRMAAudioStream *m_pAudioStream;
        RMAAudioFormat m_audioFmt;
        FiveMinuteQueue m_PacketQueue;

        static const char *zm_pDescription;
        static const char *zm_pCopyright;
        static const char *zm_pMoreInfoURL;
        static const char *zm_pStreamMimeTypes[];

        PRIVATE_DESTRUCTORS_ARE_NOT_A_CRIME
};

#endif  // __RVORBIS_H__

1.1                  vorbis-plugins/realplayer/render/make/linux-2.0-libc6-i386.mak

Index: linux-2.0-libc6-i386.mak
===================================================================
# UMAKE generated Makefile
# build choices: default,release
# platform: linux-2.0-libc6-i386
# Wed Feb  2 15:36:20 2000
.SUFFIXES: .cpp .so
.c.so:
        $(CC) $(CCFLAGS) -fPIC -DPIC -o  $@ -c $<
.cpp.so:
        $(CXX) $(CXXFLAGS) -fPIC -DPIC -o  $@ -c $<

RM = rm -f
RM_DIR = rm -rf
MAKE_DEP = makedep.py
MAKE_DEP_FLAGS =   $(INCLUDES) $(DEFINES)
MAKE_LIB = ar cr 
MAKE_LIB_FLAGS =  
RANLIB = ranlib
CP = cp
MAKE = make

# Compilers
CC = gcc
CCFLAGS = -pipe -O2  $(INCLUDES) $(DEFINES)
CXX = g++
CXXFLAGS = -pipe -O2  $(INCLUDES) $(DEFINES)

# Linker
LD = g++
LDFLAGS = -shared -L/usr/X11R6/lib -L/usr/X11R6/lib 

DEPLIBS = 

DYNAMIC_LIBS = -logg -lvorbis

SRCS = \
        ../rvorbis.cpp \
        ../fivemque.cpp

OBJS = $(COMPILED_OBJS) $(SOURCE_OBJS)

COMPILED_OBJS = \
        rel/obj/rvorbis.so \
        rel/obj/fivemque.so

SOURCE_OBJS = 

INCLUDES = \
        -I/usr/X11R6/include \
        -I/usr/X11R6/include \
        -I/home/jack/download/rmasdk_6_0/include \
        -I.. \
        -I./pub

DEFINES = \
        -D_LINUX \
        -D_REENTRANT \
        -D_UNIX \
        -D_RED_HAT_5_X_

SYSLIBS = 

LOCAL_LIBS = 

rel/rvorbis.so : rel/obj $(OBJS) $(DEPLIBS)
        if test -d rel; then echo; else mkdir rel; fi
        $(LD) $(LDFLAGS) -o rel/rvorbis.so $(OBJS) $(DYNAMIC_LIBS) $(DEPLIBS) $(LOCAL_LIBS) $(SYSLIBS) -lgcc

clean::
        $(RM) rel/rvorbis.so $(COMPILED_OBJS)

## OBJECT DEPENDANCIES
rel/obj:
        if test -d rel; then echo; else mkdir rel; fi
        if test -d rel/obj; then echo; else mkdir rel/obj; fi
rel/obj/rvorbis.so : ../rvorbis.cpp
        $(CXX) $(CXXFLAGS) -fPIC -DPIC -o rel/obj/rvorbis.so -c ../rvorbis.cpp
rel/obj/fivemque.so : ../fivemque.cpp
        $(CXX) $(CXXFLAGS) -fPIC -DPIC -o rel/obj/fivemque.so -c ../fivemque.cpp
copy:
        if test -d ../release; then echo; else mkdir ../release; fi
        cp rel/rvorbis.so ../release/rvorbis.so
depend:
        $(MAKE_DEP) $(MAKE_DEP_FLAGS) rel/obj/ $(SRCS)

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list