All pastes #366838 Raw Edit

rtsp in mplayer

public cpp v1 · immutable
#366838 ·published 2007-02-21 23:06 UTC
rendered paste body
Index: 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 };