videomedia.cxx
来自「MiniSip Client with DomainKeys Authentic」· CXX 代码 · 共 366 行
CXX
366 行
/* Copyright (C) 2004-2006 the Minisip Team This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* Copyright (C) 2004 * * Authors: Erik Eliasson <eliasson@it.kth.se> * Johan Bilien <jobi@via.ecp.fr>*/#include<config.h>#include<libminisip/video/VideoMedia.h>#include<libminisip/codecs/Codec.h>#include<libminisip/video/codec/VideoCodec.h>#include<libminisip/video/codec/AVDecoder.h>#include<libminisip/video/codec/AVCoder.h>#include<libminisip/video/grabber/Grabber.h>#include<libminisip/video/mixer/ImageMixer.h>#include<libminisip/video/display/VideoDisplay.h>#include<libminisip/sdp/SdpHeaderM.h>#include<libminisip/sdp/SdpHeaderA.h>#include<libmutil/itoa.h>#include<libmutil/massert.h>#define SOURCE_QUEUE_SIZE 7using namespace std;VideoMedia::VideoMedia( MRef<Codec *> codec, MRef<VideoDisplay *> display, MRef<ImageMixer *> mixer, MRef<Grabber *> grabber, uint32_t receivingWidth, uint32_t receivingHeight ): Media( codec ),grabber(grabber),display(display),mixer(mixer),receivingWidth(receivingWidth),receivingHeight(receivingHeight){ this->codec = dynamic_cast<VideoCodec *>(*codec); massert( this->codec ); receive = true; send = (!grabber.isNull()); this->codec->setDisplay( display ); this->codec->setGrabber( grabber ); this->codec->setEncoderCallback( this ); if( mixer ){ mixer->setOutput( *display ); mixer->init( receivingWidth, receivingHeight ); } sendingWidth = 176; sendingHeight = 144; addSdpAttribute( "framesize:34 " + itoa( receivingWidth ) + "-" + itoa( receivingHeight ) );}string VideoMedia::getSdpMediaType(){ return "video";}void VideoMedia::handleMHeader( MRef< SdpHeaderM * > m ){ string framesizeString = m->getAttribute( "framesize", 0 ); if( framesizeString != "" ){ size_t space = framesizeString.find( " " ); size_t coma = framesizeString.find( "-" ); if( space != string::npos && coma != string::npos ){ string widthString = framesizeString.substr( space+1,coma ); string heightString = framesizeString.substr( coma+1, framesizeString.size() ); sendingWidth = atoi( widthString.c_str() ); sendingHeight = atoi( heightString.c_str() ); } }}void VideoMedia::playData( MRef<RtpPacket *> packet ){ MRef<VideoMediaSource *> source = getSource( packet->getHeader().SSRC ); if( source ){ source->playData( packet ); }}void VideoMedia::sendVideoData( byte_t * data, uint32_t length, uint32_t ts, bool marker ){ Media::sendData( data, length, ts, marker );}void VideoMedia::registerMediaSource( uint32_t ssrc ){ MRef<VideoMediaSource *> source; source = new VideoMediaSource( ssrc, receivingWidth, receivingHeight ); if( mixer ){ source->getDecoder()->setHandler( *mixer ); } else{ MRef<VideoDisplay *> newdisplay = VideoDisplayRegistry::getInstance()->createDisplay( receivingWidth, receivingHeight ); source->getDecoder()->setHandler( *newdisplay ); source->display = newdisplay; if( newdisplay ){ //newdisplay->start(); } } sourcesLock.lock(); if( sources.size() == 0 ){ sourcesLock.unlock(); /* start everything */ if( mixer ){ mixer->selectMainSource( ssrc ); this->display->start(); } sourcesLock.lock(); } sources.push_back( source ); sourcesLock.unlock(); }void VideoMedia::unRegisterMediaSource( uint32_t ssrc ){ MRef<VideoMediaSource *> source = getSource( ssrc ); if( source ){ sourcesLock.lock(); sources.remove( source ); if( sources.size() == 0 ){ if( mixer ){ display->stop(); } } sourcesLock.unlock(); source->getDecoder()->close(); if( source->display ){ source->display->stop(); } }}MRef<VideoMediaSource *> VideoMedia::getSource( uint32_t ssrc ){ list<MRef<VideoMediaSource *> >::iterator i; sourcesLock.lock(); for( i = sources.begin(); i != sources.end(); i++ ){ if( (*i)->ssrc == ssrc ){ sourcesLock.unlock(); return (*i); } } sourcesLock.unlock(); return NULL;}void VideoMedia::registerMediaSender( MRef<MediaStreamSender *> sender ){ sendersLock.lock(); if( senders.size() == 0 ){ sendersLock.unlock(); codec->startSend( sendingWidth, sendingHeight ); sendersLock.lock(); } senders.push_back( sender ); sendersLock.unlock();}void VideoMedia::unRegisterMediaSender( MRef<MediaStreamSender *> sender ){ sendersLock.lock(); senders.remove( sender ); sendersLock.unlock(); if( senders.size() == 0 ){ ((VideoCodec *)*codec)->stopSend(); }}void VideoMedia::getImagesFromSources( MImage ** images, uint32_t & nImagesToMix, uint32_t mainSource ){ list< MRef<VideoMediaSource *> >::iterator i; uint32_t j = 0; sourcesLock.lock(); for( i = sources.begin(); i!= sources.end() && j < MAX_SOURCES; i++ ){ if( (*i)->ssrc != mainSource ){ images[j] = (*i)->provideFilledImage(); j++; } } nImagesToMix = j; sourcesLock.unlock();}void VideoMedia::releaseImagesToSources( MImage ** images, uint32_t nImages ){ uint32_t i; MRef<VideoMediaSource *> source; for( i = 0; i < nImages; i++ ){ if( images[i] ){ source = getSource( images[i]->ssrc ); if( source ){ source->addEmptyImage( images[i] ); } } }}VideoMediaSource::VideoMediaSource( uint32_t ssrc, uint32_t width, uint32_t height ):ssrc(ssrc),width(width),height(height){ uint8_t i; MImage * image; index = 0; packetLoss = false; firstSeqNo = true; expectedSeqNo = 0; savedPacket = NULL; display = NULL; for( i = 0; i < SOURCE_QUEUE_SIZE ; i++ ){ image = new MImage(); image->data[0] = new uint8_t[height*width]; image->data[1] = new uint8_t[height*width/2]; image->data[2] = new uint8_t[height*width/2]; image->linesize[0] = width; image->linesize[1] = width/2; image->linesize[2] = width/2; image->ssrc = ssrc; emptyImages.push_back( image ); } decoder = new AVDecoder; decoder->setSsrc( ssrc ); //decoder->init( width, height );}MImage * VideoMediaSource::provideEmptyImage(){ MImage * image; emptyImagesLock.lock(); if( emptyImages.empty() ){ fprintf( stderr, "emptyImages.empty()!\n" ); emptyImagesLock.unlock(); return NULL; } image = *emptyImages.begin(); emptyImages.pop_front(); emptyImagesLock.unlock(); return image;}MImage * VideoMediaSource::provideFilledImage(){ MImage * image; filledImagesLock.lock(); if( filledImages.empty() ){ filledImagesLock.unlock(); return NULL; } image = *filledImages.begin(); filledImages.pop_front(); filledImagesLock.unlock(); return image;}void VideoMediaSource::addEmptyImage( MImage * image ){ emptyImagesLock.lock(); emptyImages.push_back( image ); emptyImagesLock.unlock();}void VideoMediaSource::addFilledImage( MImage * image ){ filledImagesLock.lock(); filledImages.push_back( image ); filledImagesLock.unlock();}MRef<AVDecoder *> VideoMediaSource::getDecoder(){ return decoder;}void VideoMediaSource::playData( MRef<RtpPacket *> packet ){ int seqNo = packet->getHeader().getSeqNo(); if( firstSeqNo ){ expectedSeqNo = seqNo; firstSeqNo = false; } if( savedPacket ){ if( seqNo != expectedSeqNo - 2 ){ packetLoss = true; savedPacket = NULL; //merr << "Packet lost in video stream, dropping one frame(seqNo == expectedSeqNo - 2)" << end;#ifdef DEBUG_OUTPUT cerr << "Packet lost in video stream, dropping one frame (seqNo == expectedSeqNo - 2)" << endl;#endif } } else if( seqNo != expectedSeqNo ){ if( seqNo == expectedSeqNo + 1 ){ savedPacket = packet; expectedSeqNo = seqNo + 1; return; } else{ packetLoss = true; //rr << "Packet lost in video stream, dropping one frame seqNo == expectedSeqNo + 1)" << end;#ifdef DEBUG_OUTPUT cerr << "Packet lost in video stream, dropping one frame (seqNo " + itoa( seqNo ) + " == expectedSeqNo ("+itoa(expectedSeqNo)+") + 1)" << endl;#endif } } addPacketToFrame( packet ); if( savedPacket ){ expectedSeqNo = seqNo + 2; addPacketToFrame( savedPacket ); savedPacket = NULL; } else{ expectedSeqNo = seqNo + 1; } }void VideoMediaSource::addPacketToFrame( MRef<RtpPacket *> packet ){ if( !packetLoss ){ packet->getContent()[0] = 0; memcpy( frame + index, packet->getContent() , packet->getContentLength() ); index += packet->getContentLength(); } if( packet->getHeader().marker ){ if( ! packetLoss ){ /* We have a frame */ decoder->decodeFrame( frame, index ); } index = 0; packetLoss = false; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?