rendered paste bodyIndex: libmpdemux/demux_rtp_internal.h===================================================================--- libmpdemux/demux_rtp_internal.h (Revision 22306)+++ libmpdemux/demux_rtp_internal.h (Arbeitskopie)@@ -10,6 +10,11 @@ #ifndef __DEMUXER_H #include "demuxer.h" #endif+#ifdef USE_LIBAVCODEC_SO+#include <ffmpeg/avcodec.h>+#elif defined(USE_LIBAVCODEC)+#include "libavcodec/avcodec.h"+#endif } #ifndef _LIVEMEDIA_HH@@ -36,8 +41,4 @@ // "streamType": 0 => video; 1 => audio // This routine returns False if the input stream has closed-// A routine for adding our own data to an incoming RTP data stream:-Boolean insertRTPData(demuxer_t* demuxer, demux_stream_t* ds,- unsigned char* data, unsigned dataLen);- #endifIndex: libmpdemux/demux_rtp_codec.cpp===================================================================--- libmpdemux/demux_rtp_codec.cpp (Revision 22306)+++ libmpdemux/demux_rtp_codec.cpp (Arbeitskopie)@@ -6,8 +6,56 @@ #include <limits.h> #include <math.h> #include "stheader.h"+int av_base64_decode(uint8_t * out, const char *in, int out_length); }+#ifdef USE_LIBAVCODEC+AVCodecParserContext * h264parserctx;+#endif++// Copied from vlc+static unsigned char* parseH264ConfigStr( char const* configStr,+ unsigned int& configSize )+{++ char *dup, *psz;+ int i, i_records = 1;++ if( configSize )+ configSize = 0;+ if( configStr == NULL || *configStr == '\0' )+ return NULL;+ psz = dup = strdup( configStr );++ /* Count the number of comma's */+ for( psz = dup; *psz != '\0'; ++psz )+ {+ if( *psz == ',')+ {+ ++i_records;+ *psz = '\0';+ }+ }++ unsigned char *cfg = new unsigned char[5 * strlen(dup)];+ psz = dup;+ for( i = 0; i < i_records; i++ )+ {++ cfg[configSize++] = 0x00;+ cfg[configSize++] = 0x00;+ cfg[configSize++] = 0x01;+ configSize += av_base64_decode( (uint8_t*)&cfg[configSize],+ psz,+ 5 * strlen(dup) - 3 );++ psz += strlen(psz)+1;+ }+ if( dup ) free( dup );++ return cfg;+}+ static void needVideoFrameRate(demuxer_t* demuxer, MediaSubsession* subsession); // forward static Boolean@@ -63,6 +111,15 @@ } else if (strcmp(subsession->codecName(), "H264") == 0) { bih->biCompression = sh_video->format = mmioFOURCC('H','2','6','4');+ unsigned int configLen = 0;+ unsigned char* configData+ = parseH264ConfigStr(subsession->fmtp_spropparametersets(), configLen);+ sh_video->bih = bih = insertVideoExtradata(bih, configData, configLen);+ delete[] configData;+#ifdef USE_LIBAVCODEC+ av_register_codec_parser(&h264_parser);+ h264parserctx = av_parser_init(CODEC_ID_H264);+#endif needVideoFrameRate(demuxer, subsession); } else if (strcmp(subsession->codecName(), "H261") == 0) { bih->biCompression = sh_video->format@@ -172,6 +229,10 @@ wf->nBlockAlign = 1; wf->wBitsPerSample = 8; wf->cbSize = 0;+ } else if (strcmp(subsession->codecName(), "AMR") == 0) {+ wf->wFormatTag = sh_audio->format = mmioFOURCC('s','a','m','r');+ } else if (strcmp(subsession->codecName(), "AMR-WB") == 0) {+ wf->wFormatTag = sh_audio->format = mmioFOURCC('s','a','w','b'); } else if (strcmp(subsession->codecName(), "PCMU") == 0) { wf->wFormatTag = sh_audio->format = 0x7; wf->nAvgBytesPerSec = 8000;@@ -238,11 +299,36 @@ wf->wFormatTag = sh_audio->format = fourcc; wf->nChannels = numChannels;++ uint8_t *pos = (uint8_t*)qtRTPSource->qtState.sdAtom + 52;+ uint8_t *endpos = (uint8_t*)qtRTPSource->qtState.sdAtom+ + qtRTPSource->qtState.sdAtomSize;+ while (pos+8 < endpos) {+ unsigned atomLength = pos[0]<<24 | pos[1]<<16 | pos[2]<<8 | pos[3];+ if (atomLength == 0 || atomLength > endpos-pos) break;+ if (!memcmp(pos+4, "wave", 4) && fourcc==mmioFOURCC('Q','D','M','2') &&+ atomLength > 8 &&+ atomLength <= INT_MAX) {+ sh_audio->codecdata = (unsigned char*) malloc(atomLength-8);+ if (sh_audio->codecdata) {+ memcpy(sh_audio->codecdata, pos+8, atomLength-8);+ sh_audio->codecdata_len = atomLength-8;+ }+ break;+ }+ pos += atomLength;+ } } else { fprintf(stderr, "Unknown MPlayer format code for MIME type \"audio/%s\"\n", subsession->codecName()); }+unsigned char* packetData; unsigned packetDataLen;float curPTS;+for (int i=0;i<00;printf("%i ",i++))+if (!awaitRTPPacket(demuxer, demuxer->video, packetData, packetDataLen, curPTS)+|| !awaitRTPPacket(demuxer, demuxer->audio, packetData, packetDataLen, curPTS))+printf("Nicht gelungen\n");+printf("\n"); } static void needVideoFrameRate(demuxer_t* demuxer,@@ -260,6 +346,7 @@ int fps = (int)(subsession->videoFPS()); if (fps != 0) { sh_video->fps = fps;+ sh_video->frametime=1.0f/fps; return; }@@ -313,10 +400,11 @@ // contain the number of channels ("numChannels") that we want: char const* sdAtom = qtState.sdAtom; if (sdAtom == NULL || qtState.sdAtomSize < 7*4) return False;-+printf("Sound Atom: ");for (int i=0;i<qtState.sdAtomSize;i++)printf("%02X ", qtState.sdAtom[i]);printf("\n"); fourcc = *(unsigned*)(&sdAtom[4]); // put in host order char const* word7Ptr = &sdAtom[6*4]; numChannels = (word7Ptr[0]<<8)|(word7Ptr[1]); return True; }+Index: libmpdemux/demux_rtp.cpp===================================================================--- libmpdemux/demux_rtp.cpp (Revision 22306)+++ libmpdemux/demux_rtp.cpp (Arbeitskopie)@@ -65,6 +65,7 @@ ReadBufferQueue* videoBufferQueue; unsigned flags; struct timeval firstSyncTime;+ float last_pts; }; extern "C" char* network_username;@@ -325,35 +326,6 @@ return True; }-Boolean insertRTPData(demuxer_t* demuxer, demux_stream_t* ds,- unsigned char* data, unsigned dataLen) {- // Begin by finding the buffer queue that we want to add data to.- // (Get this from the RTP state, which we stored in- // the demuxer's 'priv' field)- RTPState* rtpState = (RTPState*)(demuxer->priv);- ReadBufferQueue* bufferQueue = NULL;- if (ds == demuxer->video) {- bufferQueue = rtpState->videoBufferQueue;- } else if (ds == demuxer->audio) {- bufferQueue = rtpState->audioBufferQueue;- } else {- fprintf(stderr, "(demux_rtp)insertRTPData: internal error: unknown stream\n");- return False;- }-- if (data == NULL || dataLen == 0) return False;-- demux_packet_t* dp = new_demux_packet(dataLen);- if (dp == NULL) return False;-- // Copy our data into the buffer, and save it:- memmove(dp->buffer, data, dataLen);- dp->len = dataLen;- dp->pts = 0;- bufferQueue->savePendingBuffer(dp);- return True;-}- static void teardownRTSPorSIPSession(RTPState* rtpState); // forward extern "C" void demux_close_rtp(demuxer_t* demuxer) {@@ -453,6 +425,9 @@ bufferQueue->blockingFlag = ~0; }+demux_packet_t* nextdp = NULL;+float lastpts;+ static demux_packet_t* getBuffer(demuxer_t* demuxer, demux_stream_t* ds, Boolean mustGetNewData, float& ptsBehind) {@@ -461,10 +436,15 @@ // the demuxer's 'priv' field) RTPState* rtpState = (RTPState*)(demuxer->priv); ReadBufferQueue* bufferQueue = NULL;+ sh_video_t* sh_video = NULL;+ int amr=0; if (ds == demuxer->video) { bufferQueue = rtpState->videoBufferQueue;+ sh_video = (sh_video_t*)ds->sh; } else if (ds == demuxer->audio) { bufferQueue = rtpState->audioBufferQueue;+ if (((sh_audio_t*)ds->sh)->format== mmioFOURCC('s','a','m','r'))+ amr=1; } else { fprintf(stderr, "(demux_rtp)getBuffer: internal error: unknown stream\n"); return NULL;@@ -486,13 +466,75 @@ } // Allocate a new packet buffer, and arrange to read into it:+ if (!nextdp || !sh_video) { dp = new_demux_packet(MAX_RTP_FRAME_SIZE); bufferQueue->dp = dp; if (dp == NULL) return NULL;+ }+ // Handle H264 video:+#ifdef USE_LIBAVCODEC+extern AVCodecParserContext * h264parserctx;++ if (sh_video && h264parserctx) {++ int consumed, poutbuf_size;+ uint8_t *poutbuf = NULL;++ TaskScheduler& scheduler+ = bufferQueue->readSource()->envir().taskScheduler();++ do {+ if (!nextdp) {+ dp->buffer[0]=0x00;+ dp->buffer[1]=0x00;+ dp->buffer[2]=0x01;++ bufferQueue->blockingFlag = 0;+ bufferQueue->readSource()->getNextFrame(&dp->buffer[3],+ MAX_RTP_FRAME_SIZE-3,+ afterReading, bufferQueue,+ onSourceClosure, bufferQueue);+ scheduler.doEventLoop(&bufferQueue->blockingFlag);+ } else {+ bufferQueue->dp = dp = nextdp;+ nextdp = NULL;+ }++ consumed = h264parserctx->parser->parser_parse(h264parserctx,+ (AVCodecContext*)sh_video->context,+ &poutbuf, &poutbuf_size,+ dp->buffer, dp->len+3);++ if (!consumed && !poutbuf_size)+ return NULL;++ if (!poutbuf_size) {+ lastpts=dp->pts;+ free_demux_packet(dp);+ bufferQueue->dp = dp = new_demux_packet(MAX_RTP_FRAME_SIZE);+ if (dp == NULL) return NULL;+ } else {+ nextdp = dp;+ bufferQueue->dp = dp = new_demux_packet(poutbuf_size);+ if (dp == NULL) return NULL;+ memcpy(dp->buffer, poutbuf, poutbuf_size);+ dp->len=poutbuf_size;+ dp->pts=lastpts;+ }+ } while (!poutbuf_size);+ } else+#endif //USE_LIBAVCODEC+ {++ if (amr)+ dp->buffer[0] =+ ((AMRAudioSource*)bufferQueue->readSource())->lastFrameHeader();+ // Schedule the read operation: bufferQueue->blockingFlag = 0;- bufferQueue->readSource()->getNextFrame(dp->buffer, MAX_RTP_FRAME_SIZE,+ bufferQueue->readSource()->getNextFrame(&dp->buffer[amr],+ MAX_RTP_FRAME_SIZE, afterReading, bufferQueue, onSourceClosure, bufferQueue); // Block ourselves until data becomes available:@@ -500,6 +542,23 @@ = bufferQueue->readSource()->envir().taskScheduler(); scheduler.doEventLoop(&bufferQueue->blockingFlag);+ dp->len+=amr;+ }++if (sh_video){+rtpState->last_pts=dp->pts;+mp_msg(MSGT_DEMUX, MSGL_V, "PTS: %f, len. %d; %#x %#x %#x %#x %#x %#x %#x %#x %#x %#x\n",dp->pts,dp->len,dp->buffer[0],dp->buffer[1],dp->buffer[2],dp->buffer[3],dp->buffer[4],dp->buffer[5],dp->buffer[6],dp->buffer[7],dp->buffer[10],dp->buffer[11]);+//if (dp->len>biggest){biggest=dp->len;mp_msg(MSGT_DEMUX, MSGL_INFO,"Biggest: %d \n",biggest);}+}+/*+ if (amr)+ dp->buffer[0] =+ ((AMRAudioSource*)bufferQueue->readSource())->lastFrameHeader();+...&dp->buffer[amr]+...+ dp->len+=amr;++*/ // Set the "ptsBehind" result parameter: if (bufferQueue->prevPacketPTS != 0.0 && bufferQueue->prevPacketWasSynchronized@@ -513,6 +572,7 @@ } if (mustGetNewData) {+ resize_demux_packet(dp, dp->len); // Save this buffer for future reads: bufferQueue->savePendingBuffer(dp); }@@ -582,7 +642,31 @@ return dp; }+static void demux_rtp_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {+((RTPState*)demuxer->priv)->rtspClient->playMediaSession(*((RTPState*)demuxer->priv)->mediaSession, ((RTPState*)demuxer->priv)->last_pts+rel_seek_secs);+}+static int demux_rtp_control(struct demuxer_st *demuxer, int cmd, void *arg) {+ double endpos = ((RTPState*)demuxer->priv)->mediaSession->playEndTime();++ switch(cmd) {+ case DEMUXER_CTRL_GET_TIME_LENGTH:+ if (endpos <= 0)+ return DEMUXER_CTRL_DONTKNOW;+ *((double *)arg) = endpos;+ return DEMUXER_CTRL_OK;++ case DEMUXER_CTRL_GET_PERCENT_POS:+ if (endpos <= 0)+ return DEMUXER_CTRL_DONTKNOW;+ *((int *)arg) = (int)(((RTPState*)demuxer->priv)->last_pts*100/endpos);+ return DEMUXER_CTRL_OK;++ default:+ return DEMUXER_CTRL_NOTIMPL;+ }+}+ demuxer_desc_t demuxer_desc_rtp = { "LIVE555 RTP demuxer", "rtp",@@ -595,6 +679,6 @@ demux_rtp_fill_buffer, demux_open_rtp, demux_close_rtp,- NULL,- NULL+ demux_rtp_seek,+ demux_rtp_control };