ccrtp-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Ccrtp-devel] There is bug when use multi RTP session of ccRTP!


From: Seven Pham
Subject: [Ccrtp-devel] There is bug when use multi RTP session of ccRTP!
Date: Fri, 27 May 2005 09:58:41 +0700

Hi all,
I use the ccRTP to transfer the audio and video stream. I am stick in 
a bug.  i have spent a lot of time to fix it. But I still can not pass
it. This is my problem:

My application have 2 stream: audio stream and video stream.I use 2
thread for  them. One for send/receiv audio, one for send/receive
video. They can send/receive both audio and video stream. But They
were killed(or application was segmentation fault) after about 5
minutes for streaming. if i stop one stream audio or video and use
only one stream, it can send/receive well.This is the way that i use
multi session of ccRTP:

+ For Audio stream:

class AudioRtpRTX : public Thread, public TimerPort {
public:
        AudioRtpRTX (SipCall *, AudioDrivers *, Manager *, bool, int);
        ~AudioRtpRTX();
        virtual void run ();

private:
        SipCall         *ca;
        AudioDrivers    *audioDevice;
        RTPSession      *sessionSend;
        RTPSession      *sessionRecv;
        SymmetricRTPSession     *session;
        Manager         *manager;
        bool            sym;
        int             line;
};

sessionSend and sessionRecv were created as the following source code:
               InetHostAddress local_ip("0.0.0.0");
                sessionRecv = new RTPSession (local_ip,
getLocalAudioPort(ca));//local audio port is 7070
                sessionSend = new RTPSession (local_ip);

And this is the run()  function of the thread:
void AudioRtpRTX::run(void)
{
        int gran = 160;
        int prev_ts= 0;
        AudioCodec *ac=NULL;
        unsigned char *data_to_send;
        short *data_mute;
        short *data_from_mic;
        int i, compSize, timestamp;
        int expandedSize;
        short *data_for_speakers = NULL;
        int numFrames = 0;
        data_for_speakers = (short *)malloc(2048 *sizeof(short));
        data_from_mic = (short *)malloc(1024 *sizeof( short));
        data_to_send = (unsigned char *)malloc(1024 * sizeof( unsigned char));
        data_mute = (short *)malloc(1024 * sizeof( short));

        InetHostAddress remote_ip(ca->remote_sdp_audio_ip);
        printf("Enter thread AudioRtpRTX:)-Mode %d\n", sym);
     
       //Init the Audio codec, use g711 audio codec
        ac = AudioCodec_new();

        if (!remote_ip) {
           printf("RTX: IP address is not correct!\n");
           this->exit();
        } else {
                printf("RTX: Connected to %s:%d",
                ca->remote_sdp_audio_ip, ca->remote_sdp_audio_port);
        }
       sym = 0;

        // Initialization
        if (!sym) {
                sessionRecv->setSchedulingTimeout (10000);
                sessionRecv->setExpireTimeout(1000000);

                sessionSend->setSchedulingTimeout(10000);
                sessionSend->setExpireTimeout(1000000);
        } 

        if (!sym) {

                //remote_sdp_audio_port is 7070
                if (!sessionSend->addDestination (remote_ip,
                                        (unsigned short)
ca->remote_sdp_audio_port)) {
                        printf("RTX send: could not connect to port %d",
                                        ca->remote_sdp_audio_port);

                        this->exit();
                } else {
                        printf("RTP(Send): Added destination %s:%d",
                                        remote_ip.getHostname(),
                                        (unsigned short)
ca->remote_sdp_audio_port);
                         }

                sessionRecv->setPayloadFormat(StaticPayloadFormat(sptPCMU));
                sessionSend->setPayloadFormat(StaticPayloadFormat(sptPCMU));
                setCancel(cancelImmediate);
                sessionSend->setMark(TRUE);
                sessionSend->setSessionBandwidth(4000000);

           }

        timestamp = 0;
#ifdef SET_TIMER
        // TODO: get frameSize from user config
        int frameSize = 20; // 20ms frames
        TimerPort::setTimer(frameSize);
#endif

        // start running the packet queue scheduler.
        if (!sym) {
                sessionRecv->startRunning();
                sessionSend->startRunning();
                cout << "The RTP queueRV is ";
                if( sessionRecv->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;

                cout << "The RTP queueSend is ";
                if( sessionSend->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;


        }

        while (ca->enable_audio != -1)
        {
                ////////////////////////////
                // Send session
                ////////////////////////////
                if (!manager->mute)
                {
                        i = AudioDrivers_readBuffer_with_data
(audioDevice, data_from_mic, 320);
                }
          
                // Encode acquired audio sample
                compSize = codecEncode (
                                0,
                                data_to_send,
                                data_from_mic, i);

               // Send encoded audio sample
                if (!sym)
                {
                        sessionSend->putData(timestamp, data_to_send,compSize);
                 }
                 timestamp += compSize;

                 //Recv session
                ////////////////////////////
                {

                        const AppDataUnit* adu = NULL;
                        int loop = 0;

                        Thread::sleep(5); // in msec.
                        if (!sym)
                        {
                                adu =
sessionRecv->getData(sessionRecv->getFirstTimestamp());
                        if(adu)
                        {
                               //decode the encode data 
                               expandedSize = codecDecode (
                                        0,
                                        data_for_speakers,
                                        (unsigned
char*)adu->getData(),adu->getSize());

                                // Write decoded data to sound device
                               
AudioBuffer_resize(&manager->audiodriver[line]->audio_buf,
expandedSize);
                                AudioBuffer_setData
(&manager->audiodriver[line]->audio_buf, data_for_speakers);
                                i = AudioDrivers_writeBuffer_with_data
(audioDevice, data_for_speakers, expandedSize);

                                delete adu;
                        }
                }

                // Let's wait for the next transmit cycle
#ifdef SET_TIMER
                Thread::sleep(TimerPort::getTimer());
                TimerPort::incTimer(frameSize); // 'frameSize' ms
#endif

        }
        free(data_for_speakers);
        free(data_from_mic);
        free( data_mute);
        free( data_to_send);
        this->exit();
}

If i define SET_TIMER, the quality of the audio will be very bad

+ For video stream:
The RTP session send/receive for the video stream is like the RTP
session of the audio stream:

 class VideoRtpRTX : public Thread, public TimerPort {
public:
        VideoRtpRTX (SipCall *, VideoDrivers *, Manager *, bool, int);
        ~VideoRtpRTX();
        virtual void run ();

private:
        SipCall         *ca;
        VideoDrivers    *videoDevice;
        RTPSession      *sessionSend;
        RTPSession      *sessionRecv;
        SymmetricRTPSession     *session;
        Manager         *manager;
        bool            sym;
        int             line;
};

sessionSend and sessionRecv were created as the following source code:
               InetHostAddress local_ip("0.0.0.0");
                sessionRecv = new RTPSession (local_ip,
getLocalVideoPort(ca));//local video port is 7072
                sessionSend = new RTPSession (local_ip);
And this is the run function of the thread:

void VideoRtpRTX::run(void)
{
        #define PIC_WIDTH 176
        ##define PIC_HEIGHT 144
        #define FRAME_SIZE  (PIC_WIDTH*PIC_HEIGHT*3/2) //frame size of
the YUV picture


        unsigned char *data_to_send;
        unsigned char *data_compressed;
        unsigned char *data_from_wc;
        unsigned char *data_for_lcd = NULL;
        // TODO: get frameSize from user config
        int frameSize = 100; // 100ms frames
        unsigned long numFrames = 0;
        InetHostAddress remote_ip(ca->remote_sdp_audio_ip);

        data_for_lcd = (unsigned char *)malloc(FRAME_SIZE);
        data_from_wc = (unsigned char *)malloc(FRAME_SIZE);
        data_to_send = (unsigned char *)malloc(FRAME_SIZE);
        data_compressed = (unsigned char *)malloc(FRAME_SIZE);
        printf("Enter thread VideoRtpRTX\n");

       sym = 0;
        // Initialization
        if (!sym) {
                sessionRecv->setSchedulingTimeout(120000);
                sessionRecv->setExpireTimeout(12000000);

                sessionSend->setSchedulingTimeout(120000);
                sessionSend->setExpireTimeout(12000000);
        }

        if (!sym) {

                if (!sessionSend->addDestination (remote_ip,
                                        (unsigned
short)ca->remote_sdp_video_port)) {
                        //remote_sdp_video_port is 7072
                        printf("RTX send: could not connect to port %d",
                                ca->remote_sdp_video_port);
                        free(data_for_lcd);
                        free(data_from_wc);
                        free( data_compressed);
                        free( data_to_send);
                        this->exit();


                } else {
                        printf("RTP(Send): Added destination %s:%d\n",
                                        remote_ip.getHostname(),
                                        (unsigned
short)ca->remote_sdp_video_port);
                }

                sessionRecv->setPayloadFormat(DynamicPayloadFormat(
                ca->video_payload, 90000));
                sessionSend->setPayloadFormat(DynamicPayloadFormat(
                ca->video_payload, 90000));
                 //video_payload is 96
                
                setCancel(cancelImmediate);
                sessionSend->setMark(true);
                sessionSend->setSessionBandwidth(4000000);


        }

       TimerPort::setTimer(frameSize);//100ms
        // start running the packet queue scheduler.
        if (!sym) {
                sessionRecv->startRunning();
                sessionSend->startRunning();

                cout << "The RTP queueRV is ";
                if( sessionRecv->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;

                cout << "The RTP queueSend is ";
                if( sessionSend->isActive() )
                        cout << "active." << endl;
                else
                        cout << "not active." << endl;
        }

        int packetsPerSecond = 10;
        uint16 tstampInc = sessionSend->getCurrentRTPClockRate() /
packetsPerSecond;
        while(ca->enable_video != -1)
        {

                ////////////////////////////
                // Send session
                ////////////////////////////
                //Read one frame YUV from a file into the data_from_wc buffer
                int i = readVideoFrame(data_from_wc, FRAME_SIZE);
                if( i>0 )
                {
                //right now, i use the XVID codec bitrate 40000, 10fps
                #ifdef ADD_CODEC
                        int complen;
                        int keyframe = -1;
                        complen = VideoEncImage(data_from_wc, i,
data_to_send, keyframe);
                        if(complen<0)
                        {
                                printf("encode fail");
                                continue;
                        }
                #endif
                        // send an RTP packet
                        if(!sym)
                        {
                                Thread::sleep(2);
                #ifdef ADD_CODEC
                               
sessionSend->putData(numFrames*tstampInc, data_to_send, complen);
                                numFrames++;
                #else
                               
sessionSend->putData(numFrames*tstampInc, data_from_wc,FRAME_SIZE);
                                numFrames++;
                #endif
                 }else{ //end of file, close and reopen the file
                        closeVideoInput();
                        openVideoInput(VIDEOFILE);

                }

                 ////////////////////////////
                // Recv session
                ////////////////////////////
                const AppDataUnit* adu = NULL;
                Thread::sleep(5); // in msec.
                 if (!sym) {
                      adu =
sessionRecv->getData(sessionRecv->getFirstTimestamp());

                 }

                if (adu)
                {
                        int decomplen;
        #ifdef ADD_CODEC
                        //decode the frame and write it to frame buffer
                        decomplen = VideoDecImage((unsigned
char*)adu->getData(), data_for_lcd, adu->getSize());
                        usleep(2);
                        if(decomplen<0){
                                printf("decode video image fail\n");
                                delete adu;
                                continue;
                        }

        #endif
                        //convert the yuv420p to rgb565
                        int bytes = 2;//rgb565
                        unsigned char* convm = (unsigned
char*)malloc(PIC_WIDTH*PIC_HEIGHT*bytes);
                        if(convm)
                        {
                        #ifdef ADD_CODEC
                                v4l_yuv420p2rgb (convm, (unsigned
char*)data_for_lcd,PIC_WIDTH, PIC_HEIGHT, bytes*8);
                        #else
                                v4l_yuv420p2rgb (convm, (unsigned
char*)adu->getData(),PIC_WIDTH, PIC_HEIGHT, bytes*8);
                        #endif
                                //display it to frame buffer
                                displayVideo((short*)convm);
                                free(convm);
                        }
                        else
                        {
                                printf("Can not allocate memory\n");
                        }
                        delete adu;
                }
                Thread::sleep(TimerPort::getTimer());
                TimerPort::incTimer(frameSize);
        }
        printf("Quit the video Thread Send/Recv\n");
        free(data_for_lcd);
        free(data_from_wc);
        free( data_compressed);
        free( data_to_send);
}

Do you find any problem? please give me your idea. Thanks!


                                                

-- 
--------------Seven Pham----------------




reply via email to

[Prev in Thread] Current Thread [Next in Thread]