Пример #1
0
extern "C" u_int16_t MP4AV_AudioGetSamplingWindow(
	MP4FileHandle mp4File, 
	MP4TrackId audioTrackId)
{
	u_int8_t audioType = 
		MP4GetTrackEsdsObjectTypeId(mp4File, audioTrackId);

	if (audioType == MP4_INVALID_AUDIO_TYPE) {
		return 0;
	}

	if (MP4_IS_MP3_AUDIO_TYPE(audioType)) {
		MP4AV_Mp3Header mp3Hdr =
			GetMp3Header(mp4File, audioTrackId);

		return MP4AV_Mp3GetHdrSamplingWindow(mp3Hdr);

	} else if (MP4_IS_AAC_AUDIO_TYPE(audioType)) {
		u_int8_t* pAacConfig = NULL;
		u_int32_t aacConfigLength;

		MP4GetTrackESConfiguration(
			mp4File, 
			audioTrackId,
			&pAacConfig,
			&aacConfigLength);

		if (pAacConfig == NULL || aacConfigLength < 2) {
			return 0;
		}

		u_int32_t samplingWindow =
			MP4AV_AacConfigGetSamplingWindow(pAacConfig);

		free(pAacConfig);

		return samplingWindow;

	} else if ((audioType == MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE)||
	(audioType == MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE)) {
		MP4Duration frameDuration =
			MP4GetSampleDuration(mp4File, audioTrackId, 1);

		// assumes track time scale == sampling rate
		// and constant frame size was used
		return frameDuration;
	}

	return 0;
}
Пример #2
0
//#define DEBUG_G711 1
extern "C" bool G711Hinter (MP4FileHandle mp4file, 
			    MP4TrackId trackid,
			    uint16_t maxPayloadSize)
{
  uint32_t numSamples;
  uint8_t audioType;
  MP4SampleId sampleId;
  uint32_t sampleSize;
  MP4TrackId hintTrackId;
  uint8_t payload;
  uint32_t bytes_this_hint;
  uint32_t sampleOffset;

  numSamples = MP4GetTrackNumberOfSamples(mp4file, trackid);

  if (numSamples == 0) return false;

  audioType = MP4GetTrackEsdsObjectTypeId(mp4file, trackid);

  if (audioType != MP4_ALAW_AUDIO_TYPE &&
      audioType != MP4_ULAW_AUDIO_TYPE) return false;

  hintTrackId = MP4AddHintTrack(mp4file, trackid);

  if (hintTrackId == MP4_INVALID_TRACK_ID) {
    return false;
  }
  const char *type;

  if (audioType == MP4_ALAW_AUDIO_TYPE) {
    payload = 8;
    type = "PCMA";
  } else {
    payload = 0;
    type = "PCMU";
  }

  MP4SetHintTrackRtpPayload(mp4file, hintTrackId, type, &payload, 0,NULL,
			    false);

  MP4Duration sampleDuration;
  bool have_skip;
  sampleId = 1;
  sampleSize = MP4GetSampleSize(mp4file, trackid, sampleId);
  sampleDuration = MP4GetSampleDuration(mp4file, trackid, sampleId);
  have_skip = sampleDuration != sampleSize;
  sampleOffset = 0;
  bytes_this_hint = 0;

  if (maxPayloadSize > 160) maxPayloadSize = 160;

  while (1) {
    if (bytes_this_hint == 0) {
#ifdef DEBUG_G711
      printf("Adding hint/packet\n");
#endif
      MP4AddRtpHint(mp4file, hintTrackId);
      MP4AddRtpPacket(mp4file, hintTrackId, false); // marker bit 0
    }
    uint16_t bytes_left_this_packet;
    bytes_left_this_packet = maxPayloadSize - bytes_this_hint;
    if (sampleSize >= bytes_left_this_packet) {
      MP4AddRtpSampleData(mp4file, hintTrackId, 
			  sampleId, sampleOffset, bytes_left_this_packet);
      bytes_this_hint += bytes_left_this_packet;
      sampleSize -= bytes_left_this_packet;
      sampleOffset += bytes_left_this_packet;
#ifdef DEBUG_G711
      printf("Added sample with %u bytes\n", bytes_left_this_packet);
#endif
    } else {
      MP4AddRtpSampleData(mp4file, hintTrackId, 
			  sampleId, sampleOffset, sampleSize);
      bytes_this_hint += sampleSize;
#ifdef DEBUG_G711
      printf("Added sample with %u bytes\n", sampleSize);
#endif
      sampleSize = 0;
    }

    if (bytes_this_hint >= maxPayloadSize) {
      // Write the hint
      // duration is bytes written
      MP4WriteRtpHint(mp4file, hintTrackId, bytes_this_hint);
#ifdef DEBUG_G711
      printf("Finished packet - bytes %u\n", bytes_this_hint);
#endif
      bytes_this_hint = 0;
    }
    if (sampleSize == 0) {
      // next sample
      if (have_skip && bytes_this_hint != 0) {
#ifdef DEBUG_G711
	printf("duration - ending packet - bytes %u\n", bytes_this_hint);
#endif
	MP4WriteRtpHint(mp4file, hintTrackId, bytes_this_hint);
	bytes_this_hint = 0;
      }
      sampleId++;
      if (sampleId > numSamples) {
	// finish it and exit
	if (bytes_this_hint != 0) {
	  MP4WriteRtpHint(mp4file, hintTrackId, bytes_this_hint);
	}
	return true;
      }
      sampleSize = MP4GetSampleSize(mp4file, trackid, sampleId);
      sampleDuration = MP4GetSampleDuration(mp4file, trackid, sampleId);
      have_skip = sampleDuration != sampleSize;
#ifdef DEBUG_G711
      printf("Next sample %u - size %u %u\n", sampleId, sampleSize,
	     have_skip);
#endif
      sampleOffset = 0;
    }
  }
	
  return true; // will never reach here
}
Пример #3
0
extern "C" bool MP4AV_Rfc2429Hinter (MP4FileHandle file,
				     MP4TrackId mediaTrackId,
				     uint16_t maxPayloadSize)
{
  uint32_t numSamples, maxSampleSize;
  MP4TrackId hid;
  MP4Duration duration;

  numSamples = MP4GetTrackNumberOfSamples(file, mediaTrackId);
  if (numSamples == 0) {
    return false;
  }
  maxSampleSize = MP4GetTrackMaxSampleSize(file, mediaTrackId);
  u_int8_t* pSampleBuffer = (u_int8_t*)malloc(maxSampleSize);
  if (pSampleBuffer == NULL) {
    return false;
  }

  hid = MP4AddHintTrack(file, mediaTrackId);
  if (hid == MP4_INVALID_TRACK_ID) {
    return false;
  }

  uint8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD;
  MP4SetHintTrackRtpPayload(file,
                            hid,
                            "H263-2000",
                            &payloadNumber,
                            0,
                            NULL,
                            true,
                            false);

  // strictly speaking, this is not required for H.263 - it's a quicktime
  // thing.
  u_int16_t videoWidth = MP4GetTrackVideoWidth(file, mediaTrackId);
  u_int16_t videoHeight = MP4GetTrackVideoHeight(file, mediaTrackId);
  
  char sdpString[80];
  sprintf(sdpString, "a=cliprect:0,0,%d,%d\015\012", videoHeight, videoWidth);
  
  MP4AppendHintTrackSdp(file, 
 			hid,
 			sdpString);

  for (uint32_t sid = 1; sid <= numSamples; sid++) {

    duration = MP4GetSampleDuration(file, mediaTrackId, sid);

    MP4AddRtpVideoHint(file, hid, false, 0);

    u_int32_t sampleSize = maxSampleSize;
    MP4Timestamp startTime;
    MP4Duration duration;
    MP4Duration renderingOffset;
    bool isSyncSample;

    bool rc = MP4ReadSample(file, mediaTrackId, sid,
                            &pSampleBuffer, &sampleSize,
                            &startTime, &duration,
                            &renderingOffset, &isSyncSample);

    if (!rc) {
      MP4DeleteTrack(file, hid);
      free(pSampleBuffer);
      return false;
    }

    // need to skip the first 2 bytes of the packet - it is the
    //start code
    uint16_t payload_head = htons(0x400);
    uint32_t offset = sizeof(payload_head);
    uint32_t remaining = sampleSize - sizeof(payload_head);
    while (remaining) {
      bool last_pak = false;
      uint32_t len;

      if (remaining + 2 <= maxPayloadSize) {
        len = remaining;
        last_pak = true;
      } else {
        len = maxPayloadSize - 2;
      }
      MP4AddRtpPacket(file, hid, last_pak);

      MP4AddRtpImmediateData(file, hid,
                            (u_int8_t*)&payload_head, sizeof(payload_head));
      payload_head = 0;
      MP4AddRtpSampleData(file, hid, sid,
                          offset, len);
      offset += len;
      remaining -= len;
    }
    MP4WriteRtpHint(file, hid, duration, true);
  }

  free(pSampleBuffer);

  return true;
}
Пример #4
0
QWORD MP4RtpTrack::Read(Listener *listener)
{
	int last = 0;
	uint8_t* data;
	bool isSyncSample;

	// If it's first packet of a frame
	if (!numHintSamples)
	{
		// Get number of rtp packets for this sample
		if (!MP4ReadRtpHint(mp4, hint, sampleId, &numHintSamples))
		{
			//Print error
			Error("Error reading hintt");
			//Exit
			return MP4_INVALID_TIMESTAMP;
		}

		// Get number of samples for this sample
		frameSamples = MP4GetSampleDuration(mp4, hint, sampleId);

		// Get size of sample
		frameSize = MP4GetSampleSize(mp4, hint, sampleId);

		// Get sample timestamp
		frameTime = MP4GetSampleTime(mp4, hint, sampleId);
		//Convert to miliseconds
		frameTime = MP4ConvertFromTrackTimestamp(mp4, hint, frameTime, 1000);

		// Check if it is H264 and it is a Sync frame
		if (codec==VideoCodec::H264 && MP4GetSampleSync(mp4,track,sampleId))
			// Send SEI info
			SendH263SEI(listener);

		//Get max data lenght
		BYTE *data = NULL;
		DWORD dataLen = 0;
		MP4Timestamp	startTime;
		MP4Duration	duration;
		MP4Duration	renderingOffset;

		//Get values
		data	= frame->GetData();
		dataLen = frame->GetMaxMediaLength();
		
		// Read next rtp packet
		if (!MP4ReadSample(
			mp4,				// MP4FileHandle hFile
			track,				// MP4TrackId hintTrackId
			sampleId,			// MP4SampleId sampleId,
			(u_int8_t **) &data,		// u_int8_t** ppBytes
			(u_int32_t *) &dataLen,		// u_int32_t* pNumBytes
			&startTime,			// MP4Timestamp* pStartTime
			&duration,			// MP4Duration* pDuration
			&renderingOffset,		// MP4Duration* pRenderingOffset
			&isSyncSample			// bool* pIsSyncSample
			))
		{
			Error("Error reading sample");
			//Last
			return MP4_INVALID_TIMESTAMP;
		}

		//Check type
		if (media == MediaFrame::Video)
		{
			//Get video frame
			VideoFrame *video = (VideoFrame*)frame;
			//Set lenght
			video->SetLength(dataLen);
			//Timestamp
			video->SetTimestamp(startTime*90000/timeScale);
			//Set intra
			video->SetIntra(isSyncSample);
		} else {
			//Get Audio frame
			AudioFrame *audio = (AudioFrame*)frame;
			//Set lenght
			audio->SetLength(dataLen);
			//Timestamp
			audio->SetTimestamp(startTime*8000/timeScale);
		}

		//Check listener
		if (listener)
			//Frame callback
			listener->onMediaFrame(*frame);
	}

	// if it's the last
	if (packetIndex + 1 == numHintSamples)
		//Set last mark
		last = 1;
	
	// Set mark bit
	rtp.SetMark(last);

	// Get data pointer
	data = rtp.GetMediaData();
	//Get max data lenght
	DWORD dataLen = rtp.GetMaxMediaLength();

	// Read next rtp packet
	if (!MP4ReadRtpPacket(
				mp4,				// MP4FileHandle hFile
				hint,				// MP4TrackId hintTrackId
				packetIndex++,			// u_int16_t packetIndex
				(u_int8_t **) &data,		// u_int8_t** ppBytes
				(u_int32_t *) &dataLen,		// u_int32_t* pNumBytes
				0,				// u_int32_t ssrc DEFAULT(0)
				0,				// bool includeHeader DEFAULT(true)
				1				// bool includePayload DEFAULT(true)
	))
	{
		//Error
		Error("Error reading packet [%d,%d,%d]\n", hint, track,packetIndex);
		//Exit
		return MP4_INVALID_TIMESTAMP;
	}
		

	//Check
	if (dataLen>rtp.GetMaxMediaLength())
	{
		//Error
		Error("RTP packet too big [%u,%u]\n",dataLen,rtp.GetMaxMediaLength());
		//Exit
		return MP4_INVALID_TIMESTAMP;
	}
	
	//Set lenght
	rtp.SetMediaLength(dataLen);
	// Write frame
	listener->onRTPPacket(rtp);

	// Are we the last packet in a hint?
	if (last)
	{
		// The first hint
		packetIndex = 0;
		// Go for next sample
		sampleId++;
		numHintSamples = 0;
		//Return next frame time
		return GetNextFrameTime();
	}

	// This packet is this one
	return frameTime;
}