void rtpCodecInitialize_audio(demuxer_t* demuxer,
			      MediaSubsession* subsession,
			      unsigned& flags) {
  flags = 0;
  // Create a dummy audio stream header
  // to make the main MPlayer code happy:
  sh_audio_t* sh_audio = new_sh_audio(demuxer,0);
  WAVEFORMATEX* wf = (WAVEFORMATEX*)calloc(1,sizeof(WAVEFORMATEX));
  sh_audio->wf = wf;
  demux_stream_t* d_audio = demuxer->audio;
  d_audio->sh = sh_audio; sh_audio->ds = d_audio;
  d_audio->id = sh_audio->aid;

  wf->nChannels = subsession->numChannels();

  // Map known audio MIME types to the WAVEFORMATEX parameters
  // that this program uses.  (Note that not all types need all
  // of the parameters to be set.)
  wf->nSamplesPerSec
    = subsession->rtpSource()->timestampFrequency(); // by default
  if (strcmp(subsession->codecName(), "MPA") == 0 ||
      strcmp(subsession->codecName(), "MPA-ROBUST") == 0 ||
      strcmp(subsession->codecName(), "X-MP3-DRAFT-00") == 0) {
    wf->wFormatTag = sh_audio->format = 0x55;
    // Note: 0x55 is for layer III, but should work for I,II also
    wf->nSamplesPerSec = 0; // sample rate is deduced from the data
  } else if (strcmp(subsession->codecName(), "AC3") == 0) {
    wf->wFormatTag = sh_audio->format = 0x2000;
    wf->nSamplesPerSec = 0; // sample rate is deduced from the data
  } else if (strcmp(subsession->codecName(), "X-ASF-PF") == 0) {
    ;
  } else if (strcmp(subsession->codecName(), "L16") == 0) {
    wf->wFormatTag = sh_audio->format = 0x736f7774; // "twos"
    wf->nBlockAlign = 1;
    wf->wBitsPerSample = 16;
    wf->cbSize = 0;
  } else if (strcmp(subsession->codecName(), "L8") == 0) {
    wf->wFormatTag = sh_audio->format = 0x20776172; // "raw "
    wf->nBlockAlign = 1;
    wf->wBitsPerSample = 8;
    wf->cbSize = 0;
  } else if (strcmp(subsession->codecName(), "PCMU") == 0) {
    wf->wFormatTag = sh_audio->format = 0x7;
    wf->nAvgBytesPerSec = 8000;
    wf->nBlockAlign = 1;
    wf->wBitsPerSample = 8;
    wf->cbSize = 0;
  } else if (strcmp(subsession->codecName(), "PCMA") == 0) {
    wf->wFormatTag = sh_audio->format = 0x6;
    wf->nAvgBytesPerSec = 8000;
    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(), "GSM") == 0) {
    wf->wFormatTag = sh_audio->format = mmioFOURCC('a','g','s','m');
    wf->nAvgBytesPerSec = 1650;
    wf->nBlockAlign = 33;
    wf->wBitsPerSample = 16;
    wf->cbSize = 0;
  } else if (strcmp(subsession->codecName(), "QCELP") == 0) {
    wf->wFormatTag = sh_audio->format = mmioFOURCC('Q','c','l','p');
    wf->nAvgBytesPerSec = 1750;
    wf->nBlockAlign = 35;
    wf->wBitsPerSample = 16;
    wf->cbSize = 0;
  } else if (strcmp(subsession->codecName(), "MP4A-LATM") == 0) {
    wf->wFormatTag = sh_audio->format = mmioFOURCC('m','p','4','a');
    // For the codec to work correctly, it needs "AudioSpecificConfig"
    // data, which is parsed from the "StreamMuxConfig" string that
    // was present (hopefully) in the SDP description:
    unsigned codecdata_len;
    sh_audio->codecdata
      = parseStreamMuxConfigStr(subsession->fmtp_config(),
				codecdata_len);
    sh_audio->codecdata_len = codecdata_len;
    //faad doesn't understand LATM's data length field, so omit it
    ((MPEG4LATMAudioRTPSource*)subsession->rtpSource())->omitLATMDataLengthField();
  } else if (strcmp(subsession->codecName(), "MPEG4-GENERIC") == 0) {
    wf->wFormatTag = sh_audio->format = mmioFOURCC('m','p','4','a');
    // For the codec to work correctly, it needs "AudioSpecificConfig"
    // data, which was present (hopefully) in the SDP description:
    unsigned codecdata_len;
    sh_audio->codecdata
      = parseGeneralConfigStr(subsession->fmtp_config(),
			      codecdata_len);
    sh_audio->codecdata_len = codecdata_len;
  } else if (strcmp(subsession->codecName(), "X-QT") == 0 ||
	     strcmp(subsession->codecName(), "X-QUICKTIME") == 0) {
    // QuickTime generic RTP format, as described in
    // http://developer.apple.com/quicktime/icefloe/dispatch026.html

    // We can't initialize this stream until we've received the first packet
    // that has QuickTime "sdAtom" information in the header.  So, keep
    // reading packets until we get one:
    unsigned char* packetData; unsigned packetDataLen; float pts;
    QuickTimeGenericRTPSource* qtRTPSource
      = (QuickTimeGenericRTPSource*)(subsession->rtpSource());
    unsigned fourcc, numChannels;
    do {
      if (!awaitRTPPacket(demuxer, demuxer->audio,
			  packetData, packetDataLen, pts)) {
	return;
      }
    } while (!parseQTState_audio(qtRTPSource->qtState, fourcc, numChannels));

    wf->wFormatTag = sh_audio->format = fourcc;
    wf->nChannels = numChannels;

      if (qtRTPSource->qtState.sdAtomSize > 33) {
        wf->wBitsPerSample = qtRTPSource->qtState.sdAtom[27];
        wf->nSamplesPerSec = qtRTPSource->qtState.sdAtom[32]<<8|qtRTPSource->qtState.sdAtom[33];
      }
    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());
  }
}
Example #2
0
int CLvRtspClient::InitAudio( MediaSubsession *pss )
{_STT();

	if ( !m_pRtspClient )
	{	setLastError( -200, oexT( "Invalid rtsp client object" ) );
		return 0;
	} // end if

	if ( !pss )
	{	setLastError( -201, oexT( "Invalid video object" ) );
		return 0;
	} // end if

	// Create receiver for stream
	if ( !pss->initiate() )
	{	setLastError( -203, sqbind::oex2std( oexMks( oexT( "initiate() video stream failed : " ), oexT( " : " ), m_pEnv->getResultMsg() ) ) );
		return 0;
	} // end if

	if ( !pss->rtpSource() )
	{	setLastError( -204, sqbind::oex2std( oexMks( oexT( "RTP source is null : " ), oexT( " : " ), m_pEnv->getResultMsg() ) ) );
		return 0;
	} // end if

	if ( oex::CStr8( "MP4A-LATM" ) == pss->codecName() )
	{
		((MPEG4LATMAudioRTPSource*)pss->rtpSource())->omitLATMDataLengthField();

		const char *pCfg = pss->fmtp_config();
		if ( pCfg )
		{	unsigned elen = 0;
			unsigned char *pExtra = parseStreamMuxConfigStr( pCfg, elen );
			if ( pExtra && elen )
				m_extraAudio.AppendBuffer( (const char*)pExtra, elen );

		} // end if

	} // end if

	else if ( oex::CStr8( "MPEG4-GENERIC" ) == pss->codecName() )
	{
		const char *pCfg = pss->fmtp_config();
		if ( pCfg )
		{	unsigned elen = 0;
			unsigned char *pExtra = parseGeneralConfigStr( pCfg, elen );
			if ( pExtra && elen )
				m_extraAudio.AppendBuffer( (const char*)pExtra, elen );

		} // end if

	} // end if

	// Read extradata
    const char *props = pss->fmtp_spropparametersets();
    if ( props )
    {	oex::TList< oex::CStr8 > lst = oex::CParser::Explode( props, oexT( "," ) );
        for ( oex::TList< oex::CStr8 >::iterator it; lst.Next( it ); )
        {	m_extraAudio.AppendBuffer( "\x00\x00\x01", 3 );
            m_extraAudio.Mem().appendString( oex::CBase64::Decode( *it ) );
        } // end for
    } // end if

	// Set minimum rx buffer size
	if ( 2000000 > m_nRxBufferSize )
		m_nRxBufferSize = 2000000;

	// Set rx buffer size
	int sn = pss->rtpSource()->RTPgs()->socketNum();
	increaseReceiveBufferTo( *m_pEnv, sn, m_nRxBufferSize );

	pss->rtpSource()->setPacketReorderingThresholdTime( 2000000 );

	if ( pss->codecName() )
		m_sAudioCodec = oexMbToStrPtr( pss->codecName() );

	if ( !m_pRtspClient->setupMediaSubsession( *pss, False, False ) )
	{	setLastError( -205, sqbind::oex2std( oexMks( oexT( "setupMediaSubsession() failed : " ), oexT( " : " ), m_pEnv->getResultMsg() ) ) );
		return 0;
	} // end if

	// Save away important audio parameters
	m_nAudioNumChannels = pss->numChannels();
	m_nAudioRate = pss->rtpTimestampFrequency();
	m_nAudioBps = 0;

	m_pAs = new CAudioSink( *m_pEnv );
	if ( !m_pAs )
	{	setLastError( -206, sqbind::oex2std( oexMks( oexT( "CAudioSink::createNew() failed : " ), oexT( " : " ), m_pEnv->getResultMsg() ) ) );
		return 0;
	} // end if

	m_pAs->setDataEvent( &m_evtData );
	m_pAsPss = pss;

	return 1;
}