Problems with CMdaAudioInputStream and RHTTPRequest coexisting.

Login to reply to this topic.
Thu, 2007-12-13 18:19
Joined: 2007-11-16
Forum posts: 5

Hi all,

I want to write a streaming application that sends sound to an HTTP server using HTTP POST.

Basically, I have that kind of code :

/*
*  Main classes used
*/

// Active object responsible for capturing audio
CMdaAudioInputStream iAudioInput;
// calls
MMdaAudioInputStreamCallback iAudioCallback;

// Opens an HTTP session
RHTTPSession iSession;
// Active object responsible for managing an HTTP transaction
RHTTPTransaction iTransaction;
// calls that one upon receiving data from the server
MHTTPTransactionCallback iHttpCallback;
// provided in data by this one
// MySupplier : public MHTTPDataSupplier, public MyNotify
MySupplier iPostSupplier

// Simple ring buffer acting as a pipe.
MyPipe iPipe;

/*
*  Starting the active objects
*/

// Standard initialization...

iAudioInput.Open(&iStreamSettings);
iTransaction.SubmitL();

/*
*  Callbacks
*/

iAudioCallback::MaiscBufferCopied()
{
        iPipe.Write(someBuffer);
        iPostSupplier.Notify();
}

MySupplier::Notify()
{
        iTransaction.NotifyNewRequestBodyPartL();
}

MySupplier::ReleaseData()
{
        if (iAvailableData) iTrans.NotifyNewRequestBodyPartL();
}

MySupplier::GetNextDataPart()
{
        iPipe.Read(Buffer);
}

MySupplier::OverallDataSize()
{
        return KErrNotFound;
}

On the HTTP side, only OverallDataSize is called 3 times in a row just after SubmitL.
The problem is, after that only CMdaAudioInputStream seems to run. Notify is called, an therefore iTrans.NotifyNewRequestBodyPartL, but without much effect.

Also, after closing, I'm getting a KERN-EXEC 3.

If it can be of interest, by messing some parameters and returning an OverallDataSize, I can get the program to send something and not crash, but it always sends after the audio capture has been stopped.

Did I do something wrong, is there some code missing ?

I can put more detailed code if necessary.

Thanks in advance for your help.


Thu, 2007-12-13 18:37
Joined: 2007-09-23
Forum posts: 159
Re: Problems with CMdaAudioInputStream and

You'll have to post more code

Fri, 2007-12-14 11:42
Joined: 2007-09-20
Forum posts: 116
Re: Problems with CMdaAudioInputStream and RHTTPRequest

Post more code...


Chao,
Raghav

Mon, 2007-12-17 15:56
Joined: 2007-11-16
Forum posts: 5
Re: Problems with CMdaAudioInputStream and RHTTPRequest coexisti

It took some time, but I think I've gathered everything that can be meaningful, but this is rather long Sad

// Classes

class HttpAudioStream
{
        static HttpAudioStream * New();

        TBool Start(const TDesC8& aUri);

        Pipe * iPipe;
        CAudioStreamEngine * iAudioEngine;
        CWebClientEngine   * iWebEngine;
        TBool iRunning;
};

class CAudioStreamEngine : public CBase, MMdaAudioInputStreamCallback
{
        void Record(Pipe*, BasicNotify*);

        virtual void MaiscOpenComplete(TInt aError);
        virtual void MaiscBufferCopied(TInt aError, const TDesC8& aBuffer);

        HBufC8* iStreamBuffer;

        CMdaAudioInputStream* iInputStream;
        TMdaAudioDataSettings iStreamSettings;

        Pipe*        iPipe  ;
        BasicNotify* iNotify;
};

class CWebClientEngine : public HC_EventHandler, public BasicNotify
{
        // Inherited from HC_EventHandler interface
        void TransactionEnd(TInt aStatus);
        void ClientEvent( const TDesC& aEventDescription );

        //  Inherited from BasicNotify interface
        void Notify(TInt);

        void StreamPost(const TDesC8&, Pipe*);

        RHTTPSession            iSession;
        RHTTPTransaction        iTransaction;
        TBool                   iRunning;

        HC_DataSupplier     * iPostData;
        HC_BaseEventHandler * iBaseEventHandler;
        HC_EventHandler     * iEventInterface;
}

class HC_DataSupplier : public CBase, public MHTTPDataSupplier, public BasicNotify
{
        TBool PostPipe(Pipe *);

        // methods inherited from MHTTPDataSupplier
        virtual TBool GetNextDataPart(TPtrC8& aDataPart);
        virtual void ReleaseData();
        virtual TInt OverallDataSize();
        virtual TInt Reset();
}

class HC_BaseEventHandler : public CBase, public MHTTPTransactionCallback
{
public:
        // methods from MHTTPTransactionCallback
        /*virtual*/ void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
        /*virtual*/ TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent);

        void HandleRunErrorL( TInt aError );
};

// Constructors

// First, iHttpAudioStream, an HttpAudioStream instance is created
HttpAudioStream * HttpAudioStream()
{
        iPipe = Pipe::New();
        iAudioEngine = CAudioStreamEngine::NewL(); // see ConstructL instead
        iWebEngine = CWebClientEngine::NewL(); // see ConstructL instead
}

void CAudioStreamEngine::ConstructL()
{
        iInputStream = CMdaAudioInputStream::NewL(*this);
}

void CWebClientEngine::ConstructL()
{
        iSession.OpenL();
        iPostData = HC_DataSupplier::NewL(&iTransaction); // nothing special in there : sets iTrans to "&iTransaction".
        iBaseEventHandler = HC_BaseEventHandler::NewL(this); // nothing special in there : sets iEventHandler to "this".
}

//  Starting the recording

//  class CAudioStreamAppUi : public CAknAppUi
void CAudioStreamAppUi::HandleCommandL(TInt aCommand)
{
        switch ( aCommand )
        {
                case EAudioStreamCmdRecord:
                {
                        _LIT8(myurl,"http://www.example.com/getpost.php");
                        iHttpAudioStream->Start(myurl);
                        break;
                }
        }
}

TBool HttpAudioStream::Start(const TDesC8& aUri)
{
        iAudioEngine->Record(iPipe, iWebEngine);
        iWebEngine->StreamPost(aUri, iPipe);

        return ETrue;
}

void CAudioStreamEngine::Record(Pipe* aPipe, BasicNotify* aNotify)
{
        iPipe   = aPipe  ;
        iNotify = aNotify;

        iPipe->Open();
        iInputStream->Open(&iStreamSettings);
}

void CWebClientEngine::StreamPost( const TDesC8& aUri, Pipe* aPipe )
{
        iPostData->PostPipe(aPipe);
        IssueHTTPPostL(aUri);
}

TBool HC_DataSupplier::PostPipe(Pipe * aPipe)
{
        _LIT(contentType,"text/plain");
        iReqBodyContentType = contentType;

        iPipe = aPipe;
        return ETrue;
}

void CWebClientEngine::IssueHTTPPostL(const TDesC8& aUri/*, const TDesC8& aFilePostPath,const TDesC8& aFilePath*/)
{
        TInt errCode;

        // Parse string to URI (as defined in RFC2396)
        TUriParser8 uri;
        uri.Parse(aUri);

        RStringF method = iSession.StringPool().StringF(HTTP::EPOST, RHTTPSession::GetTable());

        iTransaction = iSession.OpenTransactionL(uri, *iBaseEventHandler, method);

        RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection();
        SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent);
        SetHeaderL(hdr, HTTP::EAccept, KAccept);
        SetHeaderL(hdr, HTTP::EContentType, KContentTypeForm);

        MHTTPDataSupplier* dataSupplier = iPostData;
        iTransaction.Request().SetBody(*dataSupplier);

        iTransaction.SubmitL();
}

// Callbacks

// MMdaAudioInputStreamCallback

void CAudioStreamEngine::MaiscOpenComplete(TInt aError)
{
        // assuming here (aError==KErrNone)
        iInputStream->SetPriority(EPriorityNormal, EMdaPriorityPreferenceTime);
        iInputStream->ReadL(iStreamBuffer);
}

void CAudioStreamEngine::MaiscBufferCopied(TInt aError, const TDesC8& /*aBuffer*/)
{
        // assuming here (aError==KErrNone)
        TInt count = iPipe->Write(iStreamBuffer);
        iNotify->Notify(0);
        iInputStream->ReadL(iStreamBuffer);
}

// MHTTPDataSupplier, and the notification indicating it's been fed.

void HC_DataSupplier::Notify(TInt aEvent)
{
        if (iAvailableData) return;
        iAvailableData = ETrue;
        iTrans->NotifyNewRequestBodyPartL();
}

TBool HC_DataSupplier::GetNextDataPart(TPtrC8& aDataPart)
{
        count = iPipe->Read(Buffer);
        if (count < aDataPart.Size() ) iAvailableData = EFalse;;
        return iPipe->IsEOP(); // ETrue if pipe empty and closed by the writer, indicating last part.
}

TInt HC_DataSupplier::OverallDataSize()
{
        return KErrNotFound;
}

void HC_DataSupplier::ReleaseData()
{
        if ( iAvailableData )
        {
                iTrans->NotifyNewRequestBodyPartL();
        }
}

TInt HC_DataSupplier::Reset()
{
        DB("<Reset/>\r\n");
        return KErrNotSupported;
}

// MHTTPTransactionCallback
// Never called with provided code. By providing a (positive) return value to OverallDataSize, MHFRunL can be called AFTER the end of the audio recording.

  • Login to reply to this topic.