Beispiel #1
0
static int
handle_metadata0(rtmp_t *r, AMFObject *obj,
		 media_pipe_t *mp, char *errstr, size_t errlen)
{
  AVal metastring;
  AMFObjectProperty prop;
  prop_t *m = mp->mp_prop_metadata;


  AMFProp_GetString(AMF_GetProp(obj, NULL, 0), &metastring);

  if(!AVMATCH(&metastring, &av_onMetaData)) {
    snprintf(errstr, errlen, "No metadata in metadata packet");
    return -1;
  }
  if(RTMP_FindFirstMatchingProperty(obj, &av_duration, &prop) &&
     prop.p_type == AMF_NUMBER && prop.p_vu.p_number > 0) {
    prop_set_float(prop_create(m, "duration"), prop.p_vu.p_number);
    r->total_duration = prop.p_vu.p_number * 1000;
    mp_set_duration(mp, r->total_duration * 1000LL);
    mp_set_clr_flags(mp, MP_CAN_SEEK, 0);

    if(r->ss == NULL && !(r->va->flags & BACKEND_VIDEO_NO_SUBTITLE_SCAN))
      r->ss = sub_scanner_create(r->url, mp->mp_prop_subtitle_tracks, r->va, 0);

  } else {

    r->total_duration = 0;
    mp_set_duration(mp, AV_NOPTS_VALUE);
    mp_set_clr_flags(mp, 0, MP_CAN_SEEK);
  }

  if((RTMP_FindFirstMatchingProperty(obj, &av_videoframerate, &prop) &&
      RTMP_FindFirstMatchingProperty(obj, &av_framerate, &prop))
     && prop.p_type == AMF_NUMBER) {
    r->vframeduration = 1000000.0 / prop.p_vu.p_number;
    mp->mp_framerate.num = 1000000;
    mp->mp_framerate.den = prop.p_vu.p_number;
  }
  r->width = r->height = 0;
  if(RTMP_FindFirstMatchingProperty(obj, &av_width, &prop) &&
     prop.p_type == AMF_NUMBER)
    r->width = prop.p_vu.p_number;

  if(RTMP_FindFirstMatchingProperty(obj, &av_height, &prop) &&
     prop.p_type == AMF_NUMBER)
    r->height = prop.p_vu.p_number;

  if(r->width && r->height)
    TRACE(TRACE_DEBUG, "RTMP", "Video size %d x %d", r->width, r->height);
  return 0;

}
Beispiel #2
0
static int
handle_metadata0(rtmp_t *r, AMFObject *obj,
		 media_pipe_t *mp, char *errstr, size_t errlen)
{
  AVal metastring;
  AMFObjectProperty prop;
  prop_t *m = mp->mp_prop_metadata;


  AMFProp_GetString(AMF_GetProp(obj, NULL, 0), &metastring);

  if(!AVMATCH(&metastring, &av_onMetaData)) {
    snprintf(errstr, errlen, "No metadata in metadata packet");
    return -1;
  }
  if(!RTMP_FindFirstMatchingProperty(obj, &av_duration, &prop) ||
     prop.p_type != AMF_NUMBER) {
    snprintf(errstr, errlen, "Unable to parse total duration");
    return -1;
  }
  prop_set_float(prop_create(m, "duration"), prop.p_vu.p_number);
  r->duration = prop.p_vu.p_number;



  if(!RTMP_FindFirstMatchingProperty(obj, &av_videoframerate, &prop) ||
     prop.p_type != AMF_NUMBER) {

    if(!RTMP_FindFirstMatchingProperty(obj, &av_framerate, &prop) ||
       prop.p_type != AMF_NUMBER) {
      snprintf(errstr, errlen, "Unable to parse video framerate");
      return -1;
    }
  }
  r->vframeduration = 1000000.0 / prop.p_vu.p_number;

  r->width = r->height = 0;
  if(RTMP_FindFirstMatchingProperty(obj, &av_width, &prop) &&
     prop.p_type == AMF_NUMBER)
    r->width = prop.p_vu.p_number;

  if(RTMP_FindFirstMatchingProperty(obj, &av_height, &prop) &&
     prop.p_type == AMF_NUMBER)
    r->height = prop.p_vu.p_number;

  if(r->width && r->height)
    TRACE(TRACE_DEBUG, "RTMP", "Video size %d x %d", r->width, r->height);
  return 0;

}
Beispiel #3
0
int
OpenResumeFile(const char *flvFile,	// file name [in]
			   FILE ** file,	// opened file [out]
			   off_t * size,	// size of the file [out]
			   char **metaHeader,	// meta data read from the file [out]
			   uint32_t * nMetaHeaderSize,	// length of metaHeader [out]
			   double *duration)	// duration of the stream in ms [out]
{
	size_t bufferSize = 0;
	char hbuf[16], *buffer = NULL;

	*nMetaHeaderSize = 0;
	*size = 0;

	*file = fopen(flvFile, "r+b");
	if (!*file)
		return RD_SUCCESS;		// RD_SUCCESS, because we go to fresh file mode instead of quiting

	fseek(*file, 0, SEEK_END);
	*size = ftello(*file);
	fseek(*file, 0, SEEK_SET);

	if (*size > 0)
	{
		// verify FLV format and read header
		uint32_t prevTagSize = 0;

		// check we've got a valid FLV file to continue!
		if (fread(hbuf, 1, 13, *file) != 13)
		{
			RTMP_Log(RTMP_LOGERROR, "Couldn't read FLV file header!");
			return RD_FAILED;
		}
		if (hbuf[0] != 'F' || hbuf[1] != 'L' || hbuf[2] != 'V'
			|| hbuf[3] != 0x01)
		{
			RTMP_Log(RTMP_LOGERROR, "Invalid FLV file!");
			return RD_FAILED;
		}

		if ((hbuf[4] & 0x05) == 0)
		{
			RTMP_Log(RTMP_LOGERROR,
					 "FLV file contains neither video nor audio, aborting!");
			return RD_FAILED;
		}

		uint32_t dataOffset = AMF_DecodeInt32(hbuf + 5);
		fseek(*file, dataOffset, SEEK_SET);

		if (fread(hbuf, 1, 4, *file) != 4)
		{
			RTMP_Log(RTMP_LOGERROR, "Invalid FLV file: missing first prevTagSize!");
			return RD_FAILED;
		}
		prevTagSize = AMF_DecodeInt32(hbuf);
		if (prevTagSize != 0)
		{
			RTMP_Log(RTMP_LOGWARNING,
					 "First prevTagSize is not zero: prevTagSize = 0x%08X",
					 prevTagSize);
		}

		// go through the file to find the meta data!
		off_t pos = dataOffset + 4;
		int bFoundMetaHeader = FALSE;

		while (pos < *size - 4 && !bFoundMetaHeader)
		{
			fseeko(*file, pos, SEEK_SET);
			if (fread(hbuf, 1, 4, *file) != 4)
				break;

			uint32_t dataSize = AMF_DecodeInt24(hbuf + 1);

			if (hbuf[0] == 0x12)
			{
				if (dataSize > bufferSize)
				{
					/* round up to next page boundary */
					bufferSize = dataSize + 4095;
					bufferSize ^= (bufferSize & 4095);
					free(buffer);
					buffer = (char *)malloc(bufferSize);
					if (!buffer)
						return RD_FAILED;
				}

				fseeko(*file, pos + 11, SEEK_SET);
				if (fread(buffer, 1, dataSize, *file) != dataSize)
					break;

				AMFObject metaObj;
				int nRes = AMF_Decode(&metaObj, buffer, dataSize, FALSE);
				if (nRes < 0)
				{
					RTMP_Log(RTMP_LOGERROR, "%s, error decoding meta data packet",
							 __FUNCTION__);
					break;
				}

				AVal metastring;
				AMFProp_GetString(AMF_GetProp(&metaObj, NULL, 0), &metastring);

				if (AVMATCH(&metastring, &av_onMetaData))
				{
					AMF_Dump(&metaObj);

					*nMetaHeaderSize = dataSize;
					if (*metaHeader)
						free(*metaHeader);
					*metaHeader = (char *) malloc(*nMetaHeaderSize);
					memcpy(*metaHeader, buffer, *nMetaHeaderSize);

					// get duration
					AMFObjectProperty prop;
					if (RTMP_FindFirstMatchingProperty
						(&metaObj, &av_duration, &prop))
					{
						*duration = AMFProp_GetNumber(&prop);
						RTMP_Log(RTMP_LOGDEBUG, "File has duration: %f", *duration);
					}

					bFoundMetaHeader = TRUE;
					break;
				}
				//metaObj.Reset();
				//delete obj;
			}
			pos += (dataSize + 11 + 4);
		}

		free(buffer);
		if (!bFoundMetaHeader)
			RTMP_Log(RTMP_LOGWARNING, "Couldn't locate meta data!");
	}

	return RD_SUCCESS;
}