Beispiel #1
0
static char* PrintCntlInfo(
	MP4FileHandle mp4File,
	MP4TrackId trackId)
{
  const char *media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
  const char *typeName = "Unknown";

  if (media_data_name == NULL) {
    typeName = "Unknown - no media data name";
  } else if (strcasecmp(media_data_name, "href") == 0) {
    typeName = "ISMA Href";
  } else {
    typeName = media_data_name;
  }

  MP4Duration trackDuration = 
    MP4GetTrackDuration(mp4File, trackId);
 
  double msDuration = 
    UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId, 
						 trackDuration, MP4_MSECS_TIME_SCALE));
  char *sInfo = (char *)MP4Malloc(256);

  snprintf(sInfo, 256,
	   "%u\tcontrol\t%s, %.3f secs\n",
	   trackId, 
	   typeName,
	   msDuration / 1000.0);
  return sInfo;
}
Beispiel #2
0
void MP4BytesProperty::SetValue(const u_int8_t* pValue, u_int32_t valueSize, 
	u_int32_t index) 
{
	if (m_readOnly) {
		throw new MP4Error(EACCES, "property is read-only", m_name);
	}
	if (m_fixedValueSize) {
		if (valueSize > m_fixedValueSize) {
			throw new MP4Error("value size exceeds fixed value size",
				"MP4BytesProperty::SetValue");
		}
		if (m_values[index] == NULL) {
			m_values[index] = (u_int8_t*)MP4Calloc(m_fixedValueSize);
			m_valueSizes[index] = m_fixedValueSize;
		}
		if (pValue) {
			memcpy(m_values[index], pValue, valueSize);
		}
	} else {
		MP4Free(m_values[index]);
		if (pValue) {
			m_values[index] = (u_int8_t*)MP4Malloc(valueSize);
			memcpy(m_values[index], pValue, valueSize);
			m_valueSizes[index] = valueSize;
		} else {
			m_values[index] = NULL;
			m_valueSizes[index] = 0;
		}
	}
}
Beispiel #3
0
void MP4BytesProperty::Read(MP4File* pFile, u_int32_t index)
{
	if (m_implicit) {
		return;
	}
	MP4Free(m_values[index]);
	m_values[index] = (u_int8_t*)MP4Malloc(m_valueSizes[index]);
	pFile->ReadBytes(m_values[index], m_valueSizes[index]);
}
Beispiel #4
0
void MP4File::CreateIsmaSceneCommand(
    bool hasAudio,
    bool hasVideo,
    u_int8_t** ppBytes,
    u_int64_t* pNumBytes)
{
    // from ISMA 1.0 Tech Spec Appendix E
    static u_int8_t bifsAudioOnly[] = {
        0xC0, 0x10, 0x12,
        0x81, 0x30, 0x2A, 0x05, 0x6D, 0xC0
    };
    static u_int8_t bifsVideoOnly[] = {
        0xC0, 0x10, 0x12,
        0x61, 0x04,
        0x1F, 0xC0, 0x00, 0x00,
        0x1F, 0xC0, 0x00, 0x00,
        0x44, 0x28, 0x22, 0x82, 0x9F, 0x80
    };
    static u_int8_t bifsAudioVideo[] = {
        0xC0, 0x10, 0x12,
        0x81, 0x30, 0x2A, 0x05, 0x6D, 0x26,
        0x10, 0x41, 0xFC, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
        0x04, 0x42, 0x82, 0x28, 0x29, 0xF8
    };

    if (hasAudio && hasVideo) {
        *pNumBytes = sizeof(bifsAudioVideo);
        *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
        memcpy(*ppBytes, bifsAudioVideo, sizeof(bifsAudioVideo));

    } else if (hasAudio) {
        *pNumBytes = sizeof(bifsAudioOnly);
        *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
        memcpy(*ppBytes, bifsAudioOnly, sizeof(bifsAudioOnly));

    } else if (hasVideo) {
        *pNumBytes = sizeof(bifsVideoOnly);
        *ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
        memcpy(*ppBytes, bifsVideoOnly, sizeof(bifsVideoOnly));
    } else {
        *pNumBytes = 0;
        *ppBytes = NULL;
    }
}
Beispiel #5
0
void MP4SdpAtom::Read() 
{
	// read sdp string, length is implicit in size of atom 
	u_int64_t size = GetEnd() - m_pFile->GetPosition();
	char* data = (char*)MP4Malloc(size + 1);
	ASSERT(data != NULL);
	m_pFile->ReadBytes((u_int8_t*)data, size);
	data[size] = '\0';
	((MP4StringProperty*)m_pProperties[0])->SetValue(data);
	MP4Free(data);
}
Beispiel #6
0
static char* PrintHintInfo(
	MP4FileHandle mp4File,
	MP4TrackId trackId)
{
	MP4TrackId referenceTrackId =
		MP4GetHintTrackReferenceTrackId(mp4File, trackId);

	char* payloadName = NULL;
	if (!MP4GetHintTrackRtpPayload(mp4File, trackId, &payloadName))
	  return NULL;

	char *sInfo = (char*)MP4Malloc(256);

	snprintf(sInfo, 256, 
		"%u\thint\tPayload %s for track %u\n",
		trackId,
		payloadName,
		referenceTrackId);

	free(payloadName);

	return sInfo;
}
Beispiel #7
0
static char* PrintTrackInfo(
	MP4FileHandle mp4File,
	MP4TrackId trackId)
{
	char* trackInfo = NULL;

	const char* trackType =
		MP4GetTrackType(mp4File, trackId);
	if (trackType == NULL) return NULL;

	if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) {
		trackInfo = PrintAudioInfo(mp4File, trackId);
	} else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) {
		trackInfo = PrintVideoInfo(mp4File, trackId);
	} else if (!strcmp(trackType, MP4_HINT_TRACK_TYPE)) {
		trackInfo = PrintHintInfo(mp4File, trackId);
	} else if (strcmp(trackType, MP4_CNTL_TRACK_TYPE) == 0) {
	  trackInfo = PrintCntlInfo(mp4File, trackId);
	} else {
		trackInfo = (char*)MP4Malloc(256);
		if (!strcmp(trackType, MP4_OD_TRACK_TYPE)) {
		  snprintf(trackInfo, 256,
				"%u\tod\tObject Descriptors\n",
				trackId);
		} else if (!strcmp(trackType, MP4_SCENE_TRACK_TYPE)) {
		  snprintf(trackInfo, 256,
				"%u\tscene\tBIFS\n",
				trackId);
		} else {
		  snprintf(trackInfo, 256,
					"%u\t%s\n",
					trackId, trackType);
		}
	}

	return trackInfo;
}
Beispiel #8
0
void MP4Track::ReadChunk(MP4ChunkId chunkId, 
	u_int8_t** ppChunk, u_int32_t* pChunkSize)
{
	ASSERT(chunkId);
	ASSERT(ppChunk);
	ASSERT(pChunkSize);

	u_int64_t chunkOffset = 
		m_pChunkOffsetProperty->GetValue(chunkId - 1);

	*pChunkSize = GetChunkSize(chunkId);
	*ppChunk = (u_int8_t*)MP4Malloc(*pChunkSize);

	VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
		printf("ReadChunk: track %u id %u offset 0x"LLX" size %u (0x%x)\n",
			m_trackId, chunkId, chunkOffset, *pChunkSize, *pChunkSize));

	u_int64_t oldPos = m_pFile->GetPosition(); // only used in mode == 'w'
	try {
		m_pFile->SetPosition(chunkOffset);
		m_pFile->ReadBytes(*ppChunk, *pChunkSize);
	}
	catch (MP4Error* e) {
		// let's not leak memory
		MP4Free(*ppChunk);
		*ppChunk = NULL;

		if (m_pFile->GetMode() == 'w') {
			m_pFile->SetPosition(oldPos);
		}
		throw e;
	}

	if (m_pFile->GetMode() == 'w') {
		m_pFile->SetPosition(oldPos);
	}
}
Beispiel #9
0
//
// Clone - clone my properties to destination atom
//
// this method simplifies duplicating avcC atom properties from
// source to destination file using a single API rather than
// having to copy each property.  This API encapsulates the object
// so the application layer need not concern with each property
// thereby isolating any future changes to atom properties.
//
// ----------------------------------------
// property   description
// ----------------------------------------
//
// 0    configurationVersion
// 1    AVCProfileIndication
// 2    profile_compatibility
// 3    AVCLevelIndication
// 4    reserved
// 5    lengthSizeMinusOne
// 6    reserved
// 7    number of SPS
// 8    SPS entries
// 9    number of PPS
// 10   PPS entries
//
//
void MP4HvcCAtom::Clone(MP4HvcCAtom *dstAtom)
{
#if 1 //cwm
    MP4Property *dstProperty;
    MP4TableProperty *pTable;
    uint16_t i16;
    uint64_t i32;
    uint64_t i64;
    uint8_t *tmp;

    // source pointer Property I16
    MP4Integer16Property *spPI16;
    // source pointer Property Bytes
    MP4BytesProperty *spPB;

    // dest pointer Property I16
    MP4Integer16Property *dpPI16;
    // dest pointer Property Bytes
    MP4BytesProperty *dpPB;


    // start with defaults and reserved fields
    dstAtom->Generate();

    // 0, 4, 6 are now generated from defaults
    // leaving 1, 2, 3, 5, 7, 8, 9, 10 to export

    dstProperty=dstAtom->GetProperty(1);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        0x12);//((MP4Integer8Property *)m_pProperties[1])->GetValue()

    dstProperty=dstAtom->GetProperty(2);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        0x34);//((MP4Integer8Property *)m_pProperties[2])->GetValue()

    dstProperty=dstAtom->GetProperty(3);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        ((MP4Integer8Property *)m_pProperties[3])->GetValue());

    dstProperty=dstAtom->GetProperty(5);
    ((MP4BitfieldProperty *)dstProperty)->SetValue(
        ((MP4BitfieldProperty *)m_pProperties[5])->GetValue());

    //
    // 7 and 8 are related SPS (one set of sequence parameters)
    //
    // first the count bitfield
    //
    dstProperty=dstAtom->GetProperty(7);
    dstProperty->SetReadOnly(false);
    ((MP4BitfieldProperty *)dstProperty)->SetValue(
        ((MP4BitfieldProperty *)m_pProperties[7])->GetValue());
    dstProperty->SetReadOnly(true);

    // next export SPS Length and NAL bytes */

    // first source pointers
    pTable = (MP4TableProperty *) m_pProperties[8];
    spPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    spPB = (MP4BytesProperty *)pTable->GetProperty(1);

    // now dest pointers
    dstProperty=dstAtom->GetProperty(8);
    pTable = (MP4TableProperty *) dstProperty;
    dpPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    dpPB = (MP4BytesProperty *)pTable->GetProperty(1);

    // sps length
    i16 = spPI16->GetValue();
    i64 = i16;
    // FIXME - this leaves m_maxNumElements =2
    // but src atom m_maxNumElements is 1
    dpPI16->InsertValue(i64, 0);

    // export byte array
    i32 = i16;
    // copy bytes to local buffer
    tmp = (uint8_t *)MP4Malloc(i32);
    ASSERT(tmp != NULL);
    spPB->CopyValue(tmp, 0);
    // set element count
    dpPB->SetCount(1);
    // copy bytes
    dpPB->SetValue(tmp, i32, 0);
    MP4Free((void *)tmp);

    //
    // 9 and 10 are related PPS (one set of picture parameters)
    //
    // first the integer8 count
    //
    dstProperty=dstAtom->GetProperty(9);
    dstProperty->SetReadOnly(false);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        ((MP4Integer8Property *)m_pProperties[9])->GetValue());
    dstProperty->SetReadOnly(true);

    // next export PPS Length and NAL bytes */

    // first source pointers
    pTable = (MP4TableProperty *) m_pProperties[10];
    spPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    spPB = (MP4BytesProperty *)pTable->GetProperty(1);

    // now dest pointers
    dstProperty=dstAtom->GetProperty(10);
    pTable = (MP4TableProperty *) dstProperty;
    dpPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    dpPB = (MP4BytesProperty *)pTable->GetProperty(1);
#if 1//cwm 500
    // pps length
    i16 = spPI16->GetValue();
    i64 = i16;
    dpPI16->InsertValue(i64, 0);

    // export byte array
    i32 = i16;
    // copy bytes to local buffer
    tmp = (uint8_t *)MP4Malloc(i32);
    ASSERT(tmp != NULL);
    spPB->CopyValue(tmp, 0);
    // set element count
    dpPB->SetCount(1);
    // copy bytes
    dpPB->SetValue(tmp, i32, 0);
    MP4Free((void *)tmp);
#endif //cwm 500
#endif //cwm
}
Beispiel #10
0
void MP4RtpHintTrack::ReadPacket(
	u_int16_t packetIndex,
	u_int8_t** ppBytes, 
	u_int32_t* pNumBytes,
	u_int32_t ssrc,
	bool addHeader,
	bool addPayload)
{
	if (m_pReadHint == NULL) {
		throw new MP4Error("no hint has been read",
			"MP4ReadRtpPacket");
	}
	if (!addHeader && !addPayload) {
		throw new MP4Error("no data requested",
			"MP4ReadRtpPacket");
	}

	MP4RtpPacket* pPacket =
		m_pReadHint->GetPacket(packetIndex);

	*pNumBytes = 0;
	if (addHeader) {
		*pNumBytes += 12;
	}
	if (addPayload) {
		*pNumBytes += pPacket->GetDataSize();
	}

	// if needed, allocate the packet memory
	bool buffer_malloc = false;

	if (*ppBytes == NULL) {
		*ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
		buffer_malloc = true;
	}

	try {
		u_int8_t* pDest = *ppBytes;

		if (addHeader) {
			*pDest++ =
				0x80 | (pPacket->GetPBit() << 5) | (pPacket->GetXBit() << 4);

			*pDest++ =
				(pPacket->GetMBit() << 7) | pPacket->GetPayload();

			*((u_int16_t*)pDest) = 
				htons(m_rtpSequenceStart + pPacket->GetSequenceNumber());
			pDest += 2; 

			*((u_int32_t*)pDest) = 
				htonl(m_rtpTimestampStart + (u_int32_t)m_readHintTimestamp);
			pDest += 4; 

			*((u_int32_t*)pDest) = 
				htonl(ssrc);
			pDest += 4;
		}

		if (addPayload) {
			pPacket->GetData(pDest);
		}
	}
	catch (MP4Error* e) {
		if (buffer_malloc) {
			MP4Free(*ppBytes);
			*ppBytes = NULL;
		}
		throw e;
	}

	VERBOSE_READ_HINT(m_pFile->GetVerbosity(),
		printf("ReadPacket: %u ", packetIndex);
		MP4HexDump(*ppBytes, *pNumBytes););
Beispiel #11
0
static char* PrintAudioInfo(
	MP4FileHandle mp4File,
	MP4TrackId trackId)
{
	static const char* mpeg4AudioNames[] = {
		"MPEG-4 AAC main",
		"MPEG-4 AAC LC",
		"MPEG-4 AAC SSR",
		"MPEG-4 AAC LTP",
		"MPEG-4 AAC HE",
		"MPEG-4 AAC Scalable",
		"MPEG-4 TwinVQ",
		"MPEG-4 CELP",
		"MPEG-4 HVXC",
		NULL, NULL,
		"MPEG-4 TTSI",
		"MPEG-4 Main Synthetic",
		"MPEG-4 Wavetable Syn",
		"MPEG-4 General MIDI",
		"MPEG-4 Algo Syn and Audio FX",
		"MPEG-4 ER AAC LC",
		NULL,
		"MPEG-4 ER AAC LTP",
		"MPEG-4 ER AAC Scalable",
		"MPEG-4 ER TwinVQ",
		"MPEG-4 ER BSAC",
		"MPEG-4 ER ACC LD",
		"MPEG-4 ER CELP",
		"MPEG-4 ER HVXC",
		"MPEG-4 ER HILN",
		"MPEG-4 ER Parametric",
		"MPEG-4 SSC",
		"MPEG-4 PS",
		"MPEG-4 MPEG Surround",
		NULL,
		"MPEG-4 Layer-1",
		"MPEG-4 Layer-2",
		"MPEG-4 Layer-3",
		"MPEG-4 DST",
		"MPEG-4 Audio Lossless",
		"MPEG-4 SLS",
		"MPEG-4 SLS non-core", 
	};

	static const u_int8_t mpegAudioTypes[] = {
		MP4_MPEG2_AAC_MAIN_AUDIO_TYPE,	// 0x66
		MP4_MPEG2_AAC_LC_AUDIO_TYPE,	// 0x67
		MP4_MPEG2_AAC_SSR_AUDIO_TYPE,	// 0x68
		MP4_MPEG2_AUDIO_TYPE,			// 0x69
		MP4_MPEG1_AUDIO_TYPE,			// 0x6B
		// private types
		MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE,
		MP4_VORBIS_AUDIO_TYPE,
		MP4_ALAW_AUDIO_TYPE,
		MP4_ULAW_AUDIO_TYPE,
		MP4_G723_AUDIO_TYPE,
		MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE,
	};
	static const char* mpegAudioNames[] = {
		"MPEG-2 AAC Main",
		"MPEG-2 AAC LC",
		"MPEG-2 AAC SSR",
		"MPEG-2 Audio (13818-3)",
		"MPEG-1 Audio (11172-3)",
		// private types
		"PCM16 (little endian)",
		"Vorbis",
		"G.711 aLaw",
		"G.711 uLaw",
		"G.723.1",
		"PCM16 (big endian)",
	};
	u_int8_t numMpegAudioTypes =
		sizeof(mpegAudioTypes) / sizeof(u_int8_t);

	const char* typeName = "Unknown";
	bool foundType = false;
	u_int8_t type = 0;
	const char *media_data_name;

	media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);

	if (media_data_name == NULL) {
	  typeName = "Unknown - no media data name";
	} else if (strcasecmp(media_data_name, "samr") == 0) {
	    typeName = "AMR";
	    foundType = true;
	} else if (strcasecmp(media_data_name, "sawb") == 0) {
	    typeName = "AMR-WB";
	    foundType = true;
	} else if (strcasecmp(media_data_name, "mp4a") == 0) {
	    
	  type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
	  switch (type) {
	  case MP4_INVALID_AUDIO_TYPE:
	    typeName = "AAC from .mov";
	    foundType = true;
	    break;
	  case MP4_MPEG4_AUDIO_TYPE:  {
	
	    type = MP4GetTrackAudioMpeg4Type(mp4File, trackId);
	    if (type == MP4_MPEG4_INVALID_AUDIO_TYPE ||
		type > NUM_ELEMENTS_IN_ARRAY(mpeg4AudioNames) || 
		mpeg4AudioNames[type - 1] == NULL) {
	      typeName = "MPEG-4 Unknown Profile";
	    } else {
	      typeName = mpeg4AudioNames[type - 1];
	      foundType = true;
	    }
	    break;
	  }
	    // fall through
	  default:
	    for (u_int8_t i = 0; i < numMpegAudioTypes; i++) {
	      if (type == mpegAudioTypes[i]) {
		typeName = mpegAudioNames[i];
		foundType = true;
		break;
	      }
	    }
	  }
	} else {
	  typeName = media_data_name;
	  foundType = true;
	}

	u_int32_t timeScale =
		MP4GetTrackTimeScale(mp4File, trackId);

	MP4Duration trackDuration =
		MP4GetTrackDuration(mp4File, trackId);

	double msDuration =
		UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId,
			trackDuration, MP4_MSECS_TIME_SCALE));

	u_int32_t avgBitRate =
		MP4GetTrackBitRate(mp4File, trackId);

	char *sInfo = (char*)MP4Malloc(256);

	// type duration avgBitrate samplingFrequency
	if (foundType)
	  snprintf(sInfo, 256, 
		  "%u\taudio\t%s%s, %.3f secs, %u kbps, %u Hz\n",
		  trackId,
		  MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "",
		  typeName,
		  msDuration / 1000.0,
		  (avgBitRate + 500) / 1000,
		  timeScale);
	else
	  snprintf(sInfo, 256,
		  "%u\taudio\t%s%s(%u), %.3f secs, %u kbps, %u Hz\n",
		  trackId,
		  MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "enca - " : "",
		  typeName,
		  type,
		  msDuration / 1000.0,
		  (avgBitRate + 500) / 1000,
		  timeScale);

	return sInfo;
}
Beispiel #12
0
static char* PrintVideoInfo(
	MP4FileHandle mp4File,
	MP4TrackId trackId)
{

	static const u_int8_t mpegVideoTypes[] = {
		MP4_MPEG2_SIMPLE_VIDEO_TYPE,	// 0x60
		MP4_MPEG2_MAIN_VIDEO_TYPE,		// 0x61
		MP4_MPEG2_SNR_VIDEO_TYPE,		// 0x62
		MP4_MPEG2_SPATIAL_VIDEO_TYPE,	// 0x63
		MP4_MPEG2_HIGH_VIDEO_TYPE,		// 0x64
		MP4_MPEG2_442_VIDEO_TYPE,		// 0x65
		MP4_MPEG1_VIDEO_TYPE,			// 0x6A
		MP4_JPEG_VIDEO_TYPE,			// 0x6C
		MP4_YUV12_VIDEO_TYPE,
		MP4_H263_VIDEO_TYPE,
		MP4_H261_VIDEO_TYPE,
	};
	static const char* mpegVideoNames[] = {
		"MPEG-2 Simple",
		"MPEG-2 Main",
		"MPEG-2 SNR",
		"MPEG-2 Spatial",
		"MPEG-2 High",
		"MPEG-2 4:2:2",
		"MPEG-1",
		"JPEG",
		"YUV12",
		"H.263",
		"H.261",
	};
	u_int8_t numMpegVideoTypes =
		sizeof(mpegVideoTypes) / sizeof(u_int8_t);
	bool foundTypeName = false;
	const char* typeName = "Unknown";

	const char *media_data_name;
	char originalFormat[8];
	char  oformatbuffer[32];
	originalFormat[0] = 0;
	*oformatbuffer = 0;
	uint8_t type = 0;
	
	media_data_name = MP4GetTrackMediaDataName(mp4File, trackId);
	// encv 264b
	if (strcasecmp(media_data_name, "encv") == 0) {
	  if (MP4GetTrackMediaDataOriginalFormat(mp4File, 
						 trackId, 
						 originalFormat, 
						 sizeof(originalFormat)) == false)
	      media_data_name = NULL;
	      
	}
  
	char  typebuffer[80];
	if (media_data_name == NULL) {
	  typeName = "Unknown - no media data name";
	  foundTypeName = true;
	} else if ((strcasecmp(media_data_name, "avc1") == 0) ||
	  	(strcasecmp(originalFormat, "264b") == 0)) {
	  // avc
	  uint8_t profile, level;
	  char profileb[20], levelb[20];
	  if (MP4GetTrackH264ProfileLevel(mp4File, trackId, 
					  &profile, &level)) {
	    if (profile == 66) {
	      strcpy(profileb, "Baseline");
	    } else if (profile == 77) {
	      strcpy(profileb, "Main");
	    } else if (profile == 88) {
	      strcpy(profileb, "Extended");
	    } else if (profile == 100) {
	      strcpy(profileb, "High");
	    } else if (profile == 110) {
	      strcpy(profileb, "High 10");
	    } else if (profile == 122) {
	      strcpy(profileb, "High 4:2:2");
	    } else if (profile == 144) {
	      strcpy(profileb, "High 4:4:4");
	    } else {
	      snprintf(profileb, 20, "Unknown Profile %x", profile);
	    } 
	    switch (level) {
	    case 10: case 20: case 30: case 40: case 50:
	      snprintf(levelb, 20, "%u", level / 10);
	      break;
	    case 11: case 12: case 13:
	    case 21: case 22:
	    case 31: case 32:
	    case 41: case 42:
	    case 51:
	      snprintf(levelb, 20, "%u.%u", level / 10, level % 10);
	      break;
	    default:
	      snprintf(levelb, 20, "unknown level %x", level);
	      break;
	    }
	    if (originalFormat != NULL && originalFormat[0] != '\0') 
	      snprintf(oformatbuffer, 32, "(%s) ", originalFormat);
	    snprintf(typebuffer, sizeof(typebuffer), "H264 %s%s@%s", 
		    oformatbuffer, profileb, levelb);
	    typeName = typebuffer;
	  } else {
	    typeName = "H.264 - profile/level error";
	  }
	  foundTypeName = true;
	} else if (strcasecmp(media_data_name, "s263") == 0) {
	  // 3gp h.263
	  typeName = "H.263";
	  foundTypeName = true;
	} else if ((strcasecmp(media_data_name, "mp4v") == 0) ||
		   (strcasecmp(media_data_name, "encv") == 0)) {
	  // note encv might needs it's own field eventually.
	  type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId);
	  if (type == MP4_MPEG4_VIDEO_TYPE) {
	    type = MP4GetVideoProfileLevel(mp4File, trackId);
	    typeName = Mpeg4VisualProfileName(type);
	    if (typeName == NULL) {
	      typeName = "MPEG-4 Unknown Profile";
	    } else {
	      foundTypeName = true;
	    }
	  } else {
	    for (u_int8_t i = 0; i < numMpegVideoTypes; i++) {
	      if (type == mpegVideoTypes[i]) {
		typeName = mpegVideoNames[i];
		foundTypeName = true;
		break;
	      }
	    }
	  }
	} else {
	  typeName = media_data_name;
	  foundTypeName = true; // we don't have a type value to display
	}

	MP4Duration trackDuration =
		MP4GetTrackDuration(mp4File, trackId);

	double msDuration =
		UINT64_TO_DOUBLE(MP4ConvertFromTrackDuration(mp4File, trackId,
			trackDuration, MP4_MSECS_TIME_SCALE));

	u_int32_t avgBitRate =
		MP4GetTrackBitRate(mp4File, trackId);

	// Note not all mp4 implementations set width and height correctly
	// The real answer can be buried inside the ES configuration info
	u_int16_t width = MP4GetTrackVideoWidth(mp4File, trackId);

	u_int16_t height = MP4GetTrackVideoHeight(mp4File, trackId);

	double fps = MP4GetTrackVideoFrameRate(mp4File, trackId);

	char *sInfo = (char*)MP4Malloc(256);

	// type duration avgBitrate frameSize frameRate
	if (foundTypeName) {
	  sprintf(sInfo,
		  "%u\tvideo\t%s%s, %.3f secs, %u kbps, %ux%u @ %f fps\n",
		  trackId,
		  MP4IsIsmaCrypMediaTrack(mp4File, trackId) ? "encv - " : "",
		  typeName,
		  msDuration / 1000.0,
		  (avgBitRate + 500) / 1000,
		  width,
		  height,
		  fps
		  );
	} else {
	  sprintf(sInfo,
		  "%u\tvideo\t%s(%u), %.3f secs, %u kbps, %ux%u @ %f fps\n",
		  trackId,
		  typeName,
		  type, 
		  msDuration / 1000.0,
		  (avgBitRate + 500) / 1000,
		  width,
		  height,
		  fps
		  );
	}

	return sInfo;
}
Beispiel #13
0
void MP4Track::ReadSample(
	MP4SampleId sampleId,
	u_int8_t** ppBytes, 
	u_int32_t* pNumBytes, 
	MP4Timestamp* pStartTime, 
	MP4Duration* pDuration,
	MP4Duration* pRenderingOffset, 
	bool* pIsSyncSample)
{
	if (sampleId == MP4_INVALID_SAMPLE_ID) {
		throw new MP4Error("sample id can't be zero", 
			"MP4Track::ReadSample");
	}

	// handle unusual case of wanting to read a sample
	// that is still sitting in the write chunk buffer
	if (m_pChunkBuffer && sampleId >= m_writeSampleId - m_chunkSamples) {
		WriteChunkBuffer();
	}

	FILE* pFile = GetSampleFile(sampleId);

	if (pFile == (FILE*)-1) {
		throw new MP4Error("sample is located in an inaccessible file",
			"MP4Track::ReadSample");
	}

	u_int64_t fileOffset = GetSampleFileOffset(sampleId);

	u_int32_t sampleSize = GetSampleSize(sampleId);
	if (*ppBytes != NULL && *pNumBytes < sampleSize) {
		throw new MP4Error("sample buffer is too small",
			 "MP4Track::ReadSample");
	}
	*pNumBytes = sampleSize;

	VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
		printf("ReadSample: track %u id %u offset 0x"LLX" size %u (0x%x)\n",
			m_trackId, sampleId, fileOffset, *pNumBytes, *pNumBytes));

	bool bufferMalloc = false;
	if (*ppBytes == NULL) {
		*ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
		bufferMalloc = true;
	}

	u_int64_t oldPos = m_pFile->GetPosition(pFile); // only used in mode == 'w'
	try { 
		m_pFile->SetPosition(fileOffset, pFile);
		m_pFile->ReadBytes(*ppBytes, *pNumBytes, pFile);

		if (pStartTime || pDuration) {
			GetSampleTimes(sampleId, pStartTime, pDuration);

			VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
				printf("ReadSample:  start "LLU" duration "LLD"\n",
					(pStartTime ? *pStartTime : 0), 
					(pDuration ? *pDuration : 0)));
		}
		if (pRenderingOffset) {
			*pRenderingOffset = GetSampleRenderingOffset(sampleId);

			VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
				printf("ReadSample:  renderingOffset "LLD"\n",
					*pRenderingOffset));
		}
		if (pIsSyncSample) {
			*pIsSyncSample = IsSyncSample(sampleId);

			VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
				printf("ReadSample:  isSyncSample %u\n",
					*pIsSyncSample));
		}
	}

	catch (MP4Error* e) {
		if (bufferMalloc) {
			// let's not leak memory
			MP4Free(*ppBytes);
			*ppBytes = NULL;
		}
		if (m_pFile->GetMode() == 'w') {
			m_pFile->SetPosition(oldPos, pFile);
		}
		throw e;
	}

	if (m_pFile->GetMode() == 'w') {
		m_pFile->SetPosition(oldPos, pFile);
	}
}
Beispiel #14
0
void MP4File::CreateIsmaIodFromParams(
    u_int8_t videoProfile,
    u_int32_t videoBitrate,
    u_int8_t* videoConfig,
    u_int32_t videoConfigLength,
    u_int8_t audioProfile,
    u_int32_t audioBitrate,
    u_int8_t* audioConfig,
    u_int32_t audioConfigLength,
    u_int8_t** ppIodBytes,
    u_int64_t* pIodNumBytes)
{
    MP4IntegerProperty* pInt;
    u_int8_t* pBytes = NULL;
    u_int64_t numBytes;

    // Create the IOD
    MP4Descriptor* pIod = new MP4IODescriptor();
    pIod->SetTag(MP4IODescrTag);
    pIod->Generate();

    // Set audio and video profileLevels
    pIod->FindProperty("audioProfileLevelId",
                       (MP4Property**)&pInt);
    pInt->SetValue(audioProfile);

    pIod->FindProperty("visualProfileLevelId",
                       (MP4Property**)&pInt);
    pInt->SetValue(videoProfile);

    // Mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
    MP4DescriptorProperty* pEsProperty;
    pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
    pEsProperty->SetTags(MP4ESDescrTag);

    // Add ES Descriptors

    // Scene
    CreateIsmaSceneCommand(
        (audioProfile != 0xFF),
        (videoProfile != 0xFF),
        &pBytes,
        &numBytes);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data =\n"); MP4HexDump(pBytes, numBytes));

    char* sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);

    char* urlBuf =
        (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
    sprintf(urlBuf,
            "data:application/mpeg4-bifs-au;base64,%s",
            sceneCmdBase64);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data URL = \042%s\042\n", urlBuf));

    /* MP4Descriptor* pSceneEsd = */
    CreateESD(
        pEsProperty,
        201,				// esid
        MP4SystemsV2ObjectType,
        MP4SceneDescriptionStreamType,
        numBytes,			// bufferSize
        numBytes * 8,		// bitrate
        BifsV2Config,
        sizeof(BifsV2Config),
        urlBuf);

    MP4Free(sceneCmdBase64);
    sceneCmdBase64 = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;
    MP4Free(pBytes);
    pBytes = NULL;

    // OD

    // Video
    MP4DescriptorProperty* pVideoEsdProperty =
        new MP4DescriptorProperty();
    pVideoEsdProperty->SetTags(MP4ESDescrTag);

    /* MP4Descriptor* pVideoEsd = */
    CreateESD(
        pVideoEsdProperty,
        20,					// esid
        MP4_MPEG4_VIDEO_TYPE,
        MP4VisualStreamType,
        videoBitrate / 8,	// bufferSize
        videoBitrate,
        videoConfig,
        videoConfigLength,
        NULL);

    // Audio
    MP4DescriptorProperty* pAudioEsdProperty =
        new MP4DescriptorProperty();
    pAudioEsdProperty->SetTags(MP4ESDescrTag);

    /* MP4Descriptor* pAudioEsd = */
    CreateESD(
        pAudioEsdProperty,
        10,					// esid
        MP4_MPEG4_AUDIO_TYPE,
        MP4AudioStreamType,
        audioBitrate / 8, 	// bufferSize
        audioBitrate,
        audioConfig,
        audioConfigLength,
        NULL);

    CreateIsmaODUpdateCommandForStream(
        pAudioEsdProperty,
        pVideoEsdProperty,
        &pBytes,
        &numBytes);

    // cleanup temporary descriptor properties
    delete pAudioEsdProperty;
    delete pVideoEsdProperty;

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data = %llu bytes\n", numBytes); MP4HexDump(pBytes, numBytes));

    char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);

    urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);

    sprintf(urlBuf,
            "data:application/mpeg4-od-au;base64,%s",
            odCmdBase64);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data URL = \042%s\042\n", urlBuf));

    /* MP4Descriptor* pOdEsd = */
    CreateESD(
        pEsProperty,
        101,
        MP4SystemsV1ObjectType,
        MP4ObjectDescriptionStreamType,
        numBytes,		// bufferSize
        numBytes * 8,	// bitrate
        NULL,			// config
        0,				// configLength
        urlBuf);

    MP4Free(odCmdBase64);
    odCmdBase64 = NULL;
    MP4Free(pBytes);
    pBytes = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;

    // finally get the whole thing written to a memory
    pIod->WriteToMemory(this, ppIodBytes, pIodNumBytes);

    delete pIod;

    VERBOSE_ISMA(GetVerbosity(),
                 printf("IOD data =\n"); MP4HexDump(*ppIodBytes, *pIodNumBytes));
}
Beispiel #15
0
void MP4File::CreateIsmaIodFromFile(
    MP4TrackId odTrackId,
    MP4TrackId sceneTrackId,
    MP4TrackId audioTrackId,
    MP4TrackId videoTrackId,
    u_int8_t** ppBytes,
    u_int64_t* pNumBytes)
{
    MP4Descriptor* pIod = new MP4IODescriptor();
    pIod->SetTag(MP4IODescrTag);
    pIod->Generate();

    MP4Atom* pIodsAtom = FindAtom("moov.iods");
    ASSERT(pIodsAtom);
    MP4DescriptorProperty* pSrcIod =
        (MP4DescriptorProperty*)pIodsAtom->GetProperty(2);

    CloneIntegerProperty(pIod, pSrcIod, "objectDescriptorId");
    CloneIntegerProperty(pIod, pSrcIod, "ODProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "sceneProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "audioProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "visualProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "graphicsProfileLevelId");

    // mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
    MP4DescriptorProperty* pEsProperty;
    pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
    pEsProperty->SetTags(MP4ESDescrTag);

    MP4IntegerProperty* pSetProperty;
    MP4IntegerProperty* pSceneESID;
    MP4IntegerProperty* pOdESID;

    // OD
    MP4Descriptor* pOdEsd =
        pEsProperty->AddDescriptor(MP4ESDescrTag);
    pOdEsd->Generate();

    pOdEsd->FindProperty("ESID",
                         (MP4Property**)&pOdESID);

    // we set the OD ESID to a non-zero unique value
    pOdESID->SetValue(m_odTrackId);

    pOdEsd->FindProperty("URLFlag",
                         (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);

    u_int8_t* pBytes;
    u_int64_t numBytes;

    CreateIsmaODUpdateCommandFromFileForStream(
        audioTrackId,
        videoTrackId,
        &pBytes,
        &numBytes);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data =\n"); MP4HexDump(pBytes, numBytes));

    char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);

    char* urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);

    sprintf(urlBuf,
            "data:application/mpeg4-od-au;base64,%s",
            odCmdBase64);

    MP4StringProperty* pUrlProperty;
    pOdEsd->FindProperty("URL",
                         (MP4Property**)&pUrlProperty);
    pUrlProperty->SetValue(urlBuf);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data URL = \042%s\042\n", urlBuf));

    MP4Free(odCmdBase64);
    odCmdBase64 = NULL;
    MP4Free(pBytes);
    pBytes = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;

    MP4DescriptorProperty* pSrcDcd = NULL;

    // HACK temporarily point to scene decoder config
    FindProperty(MakeTrackName(odTrackId,
                               "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
                 (MP4Property**)&pSrcDcd);
    ASSERT(pSrcDcd);
    MP4Property* pOrgOdEsdProperty =
        pOdEsd->GetProperty(8);
    pOdEsd->SetProperty(8, pSrcDcd);

    // bufferSizeDB needs to be set appropriately
    MP4BitfieldProperty* pBufferSizeProperty = NULL;
    pOdEsd->FindProperty("decConfigDescr.bufferSizeDB",
                         (MP4Property**)&pBufferSizeProperty);
    ASSERT(pBufferSizeProperty);
    pBufferSizeProperty->SetValue(numBytes);

    // SL config needs to change from 2 (file) to 1 (null)
    pOdEsd->FindProperty("slConfigDescr.predefined",
                         (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);


    // Scene
    MP4Descriptor* pSceneEsd =
        pEsProperty->AddDescriptor(MP4ESDescrTag);
    pSceneEsd->Generate();

    pSceneEsd->FindProperty("ESID",
                            (MP4Property**)&pSceneESID);
    // we set the Scene ESID to a non-zero unique value
    pSceneESID->SetValue(sceneTrackId);

    pSceneEsd->FindProperty("URLFlag",
                            (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);

    CreateIsmaSceneCommand(
        MP4_IS_VALID_TRACK_ID(audioTrackId),
        MP4_IS_VALID_TRACK_ID(videoTrackId),
        &pBytes,
        &numBytes);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data =\n"); MP4HexDump(pBytes, numBytes));

    char *sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);

    urlBuf = (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
    sprintf(urlBuf,
            "data:application/mpeg4-bifs-au;base64,%s",
            sceneCmdBase64);

    pSceneEsd->FindProperty("URL",
                            (MP4Property**)&pUrlProperty);
    pUrlProperty->SetValue(urlBuf);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data URL = \042%s\042\n", urlBuf));

    MP4Free(sceneCmdBase64);
    sceneCmdBase64 = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;
    MP4Free(pBytes);
    pBytes = NULL;

    // HACK temporarily point to scene decoder config
    FindProperty(MakeTrackName(sceneTrackId,
                               "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
                 (MP4Property**)&pSrcDcd);
    ASSERT(pSrcDcd);
    MP4Property* pOrgSceneEsdProperty =
        pSceneEsd->GetProperty(8);
    pSceneEsd->SetProperty(8, pSrcDcd);

    // bufferSizeDB needs to be set
    pBufferSizeProperty = NULL;
    pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB",
                            (MP4Property**)&pBufferSizeProperty);
    ASSERT(pBufferSizeProperty);
    pBufferSizeProperty->SetValue(numBytes);

    // SL config needs to change from 2 (file) to 1 (null)
    pSceneEsd->FindProperty("slConfigDescr.predefined",
                            (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);


    // finally get the whole thing written to a memory
    pIod->WriteToMemory(this, ppBytes, pNumBytes);


    // now carefully replace esd properties before destroying
    pOdEsd->SetProperty(8, pOrgOdEsdProperty);
    pSceneEsd->SetProperty(8, pOrgSceneEsdProperty);
    pSceneESID->SetValue(0); // restore 0 value
    pOdESID->SetValue(0);

    delete pIod;

    VERBOSE_ISMA(GetVerbosity(),
                 printf("IOD data =\n"); MP4HexDump(*ppBytes, *pNumBytes));
}