示例#1
0
文件: ebml.c 项目: ihling/mpv
/*
 * Skip the current element, or on error, call ebml_resync_cluster().
 */
int ebml_read_skip_or_resync_cluster(stream_t *s, uint64_t *length)
{
    uint64_t len;
    int l;

    len = ebml_read_length(s, &l);
    if (len == EBML_UINT_INVALID)
        goto resync;

    if (length)
        *length = len + l;

    int64_t pos = stream_tell(s);

    // When reading corrupted elements, len will often be a random high number,
    // and stream_skip() will fail when skipping past EOF.
    if (!stream_skip(s, len)) {
        stream_seek(s, pos);
        goto resync;
    }

    return 0;

resync:
    return ebml_resync_cluster(s) < 0 ? -1 : 1;
}
static int
demux_mkv_read_cluster(FILE *s, mkv_demuxer_t *mkv_d)
{
	uint64_t length, l;
	int il;

	length = ebml_read_length (s, NULL);
	while (length > 0)
	{
		switch (ebml_read_id (s, &il))
		{
			case MATROSKA_ID_BLOCKGROUP:
				demux_mkv_read_block(s, mkv_d);
				return 1;
				break;
			case EBML_ID_INVALID:
				return 0;
			default:
				ebml_read_skip (s, &l);
				break;
		}
		length -= l + il;
	}

	return 1;
}
示例#3
0
/*
 * Read the next element as an ASCII string.
 */
char *
ebml_read_ascii (stream_t *s, uint64_t *length)
{
  uint64_t len;
  char *str;
  int l;

  len = ebml_read_length (s, &l);
  if (len == EBML_UINT_INVALID)
    return NULL;
  if (len > SIZE_MAX - 1)
    return NULL;
  if (length)
    *length = len + l;

  str = malloc (len + 1);
  if (stream_read(s, str, len) != (int) len)
    {
      free (str);
      return NULL;
    }
  str[len] = '\0';

  return str;
}
static int
demux_mkv_read_tracks (FILE *s, mkv_demuxer_t *mkv_d)
{
  uint64_t length, l;
  int il;

  mkv_d->tracks = (mkv_track_t**)malloc (sizeof (*mkv_d->tracks));
  mkv_d->num_tracks = 0;

  length = ebml_read_length (s, NULL);
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_TRACKENTRY:
          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n");
          mkv_d->tracks = (mkv_track_t**)realloc (mkv_d->tracks,
                                   (mkv_d->num_tracks+1)
                                   *sizeof (*mkv_d->tracks));
          l = demux_mkv_read_trackentry (s, mkv_d);
          if (l == 0)
            return 1;
          break;

        default:
            ebml_read_skip (s, &l);
            break;
        }
      length -= l + il;
    }
  return 0;
}
示例#5
0
文件: ebml.c 项目: kax4/mpv
/*
 * Read the next element as a float.
 */
double ebml_read_float(stream_t *s, uint64_t *length)
{
    double value;
    uint64_t len;
    int l;

    len = ebml_read_length(s, &l);
    switch (len) {
    case 4:
        value = av_int2float(stream_read_dword(s));
        break;

    case 8:
        value = av_int2double(stream_read_qword(s));
        break;

    default:
        return EBML_FLOAT_INVALID;
    }

    if (length)
        *length = len + l;

    return value;
}
static int
demux_mkv_read_trackaudio (FILE *s, mkv_track_t *track)
{
  uint64_t len, length, l;
  int il;

  track->a_sfreq = 8000.0;
  track->a_channels = 1;

  len = length = ebml_read_length (s, &il);
  len += il;
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_AUDIOSAMPLINGFREQ:
          {
            long double num = ebml_read_float (s, &l);
            if (num == EBML_FLOAT_INVALID)
              return 0;
            track->a_sfreq = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Sampling frequency: %f\n",
                    track->a_sfreq);
            break;
          }

        case MATROSKA_ID_AUDIOBITDEPTH:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->a_bps = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Bit depth: %u\n",
                    track->a_bps);
            break;
          }

        case MATROSKA_ID_AUDIOCHANNELS:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->a_channels = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Channels: %u\n",
                    track->a_channels);
            break;
          }

        default:
            ebml_read_skip (s, &l);
            break;
        }
      length -= l + il;
    }
  return len;
}
示例#7
0
文件: ebml.c 项目: AppleNuts/mpv
/*
 * Read the next element as an unsigned int.
 */
uint64_t ebml_read_uint(stream_t *s)
{
    uint64_t len, value = 0;

    len = ebml_read_length(s);
    if (len == EBML_UINT_INVALID || len < 1 || len > 8)
        return EBML_UINT_INVALID;

    while (len--)
        value = (value << 8) | stream_read_char(s);

    return value;
}
示例#8
0
文件: ebml.c 项目: kax4/mpv
/*
 * Skip the next element.
 */
int ebml_read_skip(stream_t *s, uint64_t *length)
{
    uint64_t len;
    int l;

    len = ebml_read_length(s, &l);
    if (len == EBML_UINT_INVALID)
        return 1;
    if (length)
        *length = len + l;

    stream_skip(s, len);

    return 0;
}
示例#9
0
文件: ebml.c 项目: kax4/mpv
/*
 * Read the next element, but only the header. The contents
 * are supposed to be sub-elements which can be read separately.
 */
uint32_t ebml_read_master(stream_t *s, uint64_t *length)
{
    uint64_t len;
    uint32_t id;

    id = ebml_read_id(s, NULL);
    if (id == EBML_ID_INVALID)
        return id;

    len = ebml_read_length(s, NULL);
    if (len == EBML_UINT_INVALID)
        return EBML_ID_INVALID;
    if (length)
        *length = len;

    return id;
}
示例#10
0
/*
 * Read the next element as an unsigned int.
 */
uint64_t
ebml_read_uint (FILE *s, uint64_t *length)
{
  uint64_t len, value = 0;
  int l;

  len = ebml_read_length (s, &l);
  if (len == EBML_UINT_INVALID || len < 1 || len > 8)
    return EBML_UINT_INVALID;
  if (length)
    *length = len + l;

  while (len--)
    value = (value << 8) | read_char (s);

  return value;
}
static int
demux_mkv_read_info (FILE *s, mkv_demuxer_t *mkv_d)
{
  uint64_t length, l;
  int il;
  uint64_t tc_scale = 1000000;
  long double duration = 0.;

  length = ebml_read_length (s, NULL);
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_TIMECODESCALE:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 1;
            tc_scale = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n",
                    tc_scale);
            break;
          }

        case MATROSKA_ID_DURATION:
          {
            long double num = ebml_read_float (s, &l);
            if (num == EBML_FLOAT_INVALID)
              return 1;
            duration = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n",
                    duration * tc_scale / 1000000000.0);
            break;
          }

        default:
          ebml_read_skip (s, &l);
          break;
        }
      length -= l + il;
    }
  mkv_d->tc_scale = tc_scale;
  mkv_d->duration = duration * tc_scale / 1000000000.0;
  return 0;
}
示例#12
0
文件: ebml.c 项目: AppleNuts/mpv
/*
 * Read the next element as a signed int.
 */
int64_t ebml_read_int(stream_t *s)
{
    uint64_t value = 0;
    uint64_t len;
    int l;

    len = ebml_read_length(s);
    if (len == EBML_UINT_INVALID || len < 1 || len > 8)
        return EBML_INT_INVALID;

    len--;
    l = stream_read_char(s);
    if (l & 0x80)
        value = -1;
    value = (value << 8) | l;
    while (len--)
        value = (value << 8) | stream_read_char(s);

    return (int64_t)value; // assume complement of 2
}
示例#13
0
文件: ebml.c 项目: kax4/mpv
/*
 * Read the next element as a signed int.
 */
int64_t ebml_read_int(stream_t *s, uint64_t *length)
{
    int64_t value = 0;
    uint64_t len;
    int l;

    len = ebml_read_length(s, &l);
    if (len == EBML_UINT_INVALID || len < 1 || len > 8)
        return EBML_INT_INVALID;
    if (length)
        *length = len + l;

    len--;
    l = stream_read_char(s);
    if (l & 0x80)
        value = -1;
    value = (value << 8) | l;
    while (len--)
        value = (value << 8) | stream_read_char(s);

    return value;
}
示例#14
0
文件: ebml.c 项目: AppleNuts/mpv
/*
 * Skip the current element.
 * end: the end of the parent element or -1 (for robust error handling)
 */
int ebml_read_skip(struct mp_log *log, int64_t end, stream_t *s)
{
    uint64_t len;

    int64_t pos = stream_tell(s);

    len = ebml_read_length(s);
    if (len == EBML_UINT_INVALID)
        goto invalid;

    int64_t pos2 = stream_tell(s);
    if (len >= INT64_MAX - pos2 || (end > 0 && pos2 + len > end))
        goto invalid;

    if (!stream_skip(s, len))
        goto invalid;

    return 0;

invalid:
    mp_err(log, "Invalid EBML length at position %"PRId64"\n", pos);
    stream_seek(s, pos);
    return 1;
}
int MKV_Parser(FILE *fp, FileInfo *finfo)
{
	int nRet = 0, cont = 0, ii, jj;
	int is_hw_notsupport = 0;
	nRet = mkv_check_file(fp, finfo);
	mkv_track_t *track;

	if (nRet == 0)
		return nRet;

	mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] Found the head...\n");

	if (ebml_read_id (fp, NULL) != MATROSKA_ID_SEGMENT)
	{
		mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] but no segment :(\n");
		return 0;
	}
	ebml_read_length (fp, NULL);  /* return bytes number until EOF */

	mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] + a segment...\n");

	mkv_demuxer_t *mkv_d = (mkv_demuxer_t *)calloc (1, sizeof (mkv_demuxer_t));
	finfo->priv = mkv_d;
	mkv_d->tc_scale = 1000000;
	mkv_d->segment_start = read_tell (fp);
	mkv_d->parsed_cues = (off_t *)malloc (sizeof (off_t));
	mkv_d->parsed_seekhead = (off_t *)malloc (sizeof (off_t));

	while (!cont)
	{
		switch (ebml_read_id (fp, NULL))
		{
			case MATROSKA_ID_INFO:
				mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ segment information...\n");
				cont = demux_mkv_read_info (fp, mkv_d);
				break;

			case MATROSKA_ID_TRACKS:
				mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ segment tracks...\n");
				cont = demux_mkv_read_tracks (fp, mkv_d);
				break;

			case MATROSKA_ID_CUES:
			case MATROSKA_ID_TAGS:
			case MATROSKA_ID_SEEKHEAD:
			case MATROSKA_ID_CHAPTERS:
			case MATROSKA_ID_ATTACHMENTS:
				ebml_read_skip (fp, NULL);
				break;
			case MATROSKA_ID_CLUSTER:
				mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |+ found cluster, headers are "
						"parsed completely :)\n");
				demux_mkv_read_cluster(fp, mkv_d);
				cont = 1;
				break;

			default:
				cont = 1;
			case EBML_ID_VOID:
				ebml_read_skip (fp, NULL);
				break;
		}
	}

	/* select video track */
	track = NULL;
	/* search for a video track that has the 'default' flag set */
	/*
	for (ii=0; ii<mkv_d->num_tracks; ii++)
		if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_VIDEO
				&& mkv_d->tracks[ii]->default_track)
		{
			if (mkv_d->tracks[ii]->hw_notsupport == 1)
			{
				is_hw_notsupport = 1;
				break;
			} else {
				track = mkv_d->tracks[ii];
				break;
			}
		}
		*/

	if (track == NULL)
	{
		int comp_algo_support = 1;
		/* no track has the 'default' flag set */
		/* let's take the first video track */
		for (ii=0; ii<mkv_d->num_tracks; ii++)
		{
			if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_VIDEO)
			{
				if(mkv_d->tracks[ii]->hw_notsupport == 1)
				{
					is_hw_notsupport = 1;
				} else {
					track = mkv_d->tracks[ii];

					for (jj=0; jj < track->num_encodings; jj++)
					{
						mp_msg(MSGT_DEMUX, MSGL_V, "num_encodings: %d, comp algo: %d\n",
								track->num_encodings,
								track->encodings->comp_algo);
                      if (track->encodings->comp_algo != 0 && track->encodings->comp_algo != 2 &&track->encodings->comp_algo != 3)
					  {
						  printf("MKV: Video track %d has been compressed\n", track->tnum);
						  comp_algo_support = 0;
					  }
					}
					if (comp_algo_support == 0)
						continue;
					else
					{
						comp_algo_support = 1;
						break;
					}
				}
			}
		}
		if (comp_algo_support == 0)
		{
			goto mkv_parse_err;
		}
	}
	if (track != NULL)
	{
		if (demux_mkv_open_video(finfo, track) == 0)
		{
			finfo->bVideo = 1;
			finfo->FileDuration = mkv_d->duration;
			nRet = 1;
		}
	}

	if ((track == NULL) && (is_hw_notsupport == 1))
	{
		// the only video is not support.
	}
	else 
	{

		/* select audio track */
		track = NULL;
		/* search for an audio track that has the 'default' flag set */
		/*
		for (ii=0; ii < mkv_d->num_tracks; ii++)
		{
			if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_AUDIO
					&& mkv_d->tracks[ii]->default_track)
			{
				track = mkv_d->tracks[ii];
				break;
			}
		}
		*/

		if (track == NULL)
		{
			/* no track has the 'default' flag set */
			/* let's take the first audio track */
			for (ii=0; ii < mkv_d->num_tracks; ii++)
			{
				if (mkv_d->tracks[ii]->type == MATROSKA_TRACK_AUDIO)
				{
					track = mkv_d->tracks[ii];
					int comp_algo_support = 1;

					for (jj=0; jj < track->num_encodings; jj++)
					{
						mp_msg(MSGT_DEMUX, MSGL_V, "num_encodings: %d, comp algo: %d\n",
								track->num_encodings,
								track->encodings->comp_algo);
                      if (track->encodings->comp_algo != 0 && track->encodings->comp_algo != 2 &&track->encodings->comp_algo != 3)
					  {
						  printf("MKV: Audio track %d has been compressed\n", track->tnum);
						  comp_algo_support = 0;
					  }
					}
					if (demux_mkv_open_audio(finfo, track) == 0)
					{
						finfo->bAudio = 1;
						finfo->AudioDuration = mkv_d->duration;
						finfo->AudioType = track->a_formattag;
						if (comp_algo_support == 1)
						{
							nRet = 1;
							if (check_audio_type(track->a_formattag, track->a_channels, finfo->hw_a_flag) == 1)
							{
								break;
							}
						} else {
							nRet = 0;
						}
					} else {
						nRet = 0;
					}
				}
			}
		}
	}

mkv_parse_err:
	if (mkv_d != NULL)
	{
		demux_close_mkv(mkv_d);
		finfo->priv = NULL;
	}

	return nRet;
}
static int
demux_mkv_read_trackvideo (FILE *s, mkv_track_t *track)
{
  uint64_t len, length, l;
  int il;

  len = length = ebml_read_length (s, &il);
  len += il;
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_VIDEOFRAMERATE:
          {
            long double num = ebml_read_float (s, &l);
            if (num == EBML_FLOAT_INVALID)
              return 0;
            track->v_frate = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Frame rate: %f\n",
                    track->v_frate);
            if (track->v_frate > 0)
              track->default_duration = 1 / track->v_frate;
            break;
          }

        case MATROSKA_ID_VIDEODISPLAYWIDTH:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->v_dwidth = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Display width: %u\n",
                    track->v_dwidth);
            break;
          }

        case MATROSKA_ID_VIDEODISPLAYHEIGHT:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->v_dheight = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Display height: %u\n",
                    track->v_dheight);
            break;
          }

        case MATROSKA_ID_VIDEOPIXELWIDTH:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->v_width = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Pixel width: %u\n",
                    track->v_width);
            break;
          }

        case MATROSKA_ID_VIDEOPIXELHEIGHT:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              return 0;
            track->v_height = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |   + Pixel height: %u\n",
                    track->v_height);
            break;
          }

        default:
            ebml_read_skip (s, &l);
            break;
        }
      length -= l + il;
    }
  return len;
}
static int
demux_mkv_read_trackencodings (FILE *s, mkv_track_t *track)
{
  mkv_content_encoding_t *ce, e;
  uint64_t len, length, l;
  int il, n;

  ce = (mkv_content_encoding_t *)malloc (sizeof (*ce));
  n = 0;

  len = length = ebml_read_length (s, &il);
  if (len == EBML_UINT_INVALID)
	  goto err_out;
  len += il;
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_CONTENTENCODING:
          {
            uint64_t len;
            int i;

            memset (&e, 0, sizeof (e));
            e.scope = 1;

            len = ebml_read_length (s, &i);
	    if (len == EBML_UINT_INVALID)
		    goto err_out;
            l = len + i;

            while (len > 0)
              {
                uint64_t num, ll;
                int iil;

                switch (ebml_read_id (s, &iil))
                  {
                  case MATROSKA_ID_CONTENTENCODINGORDER:
                    num = ebml_read_uint (s, &ll);
                    if (num == EBML_UINT_INVALID)
                      goto err_out;
                    e.order = num;
                    break;

                  case MATROSKA_ID_CONTENTENCODINGSCOPE:
                    num = ebml_read_uint (s, &ll);
                    if (num == EBML_UINT_INVALID)
                      goto err_out;
                    e.scope = num;
                    break;

                  case MATROSKA_ID_CONTENTENCODINGTYPE:
                    num = ebml_read_uint (s, &ll);
                    if (num == EBML_UINT_INVALID)
                      goto err_out;
                    e.type = num;
                    break;

                  case MATROSKA_ID_CONTENTCOMPRESSION:
                    {
                      uint64_t le;

                      le = ebml_read_length (s, &i);
		      if (le == EBML_UINT_INVALID)
			      goto err_out;
                      ll = le + i;

                      while (le > 0)
                        {
                          uint64_t lll;
                          int iiil;

                          switch (ebml_read_id (s, &iiil))
                            {
                            case MATROSKA_ID_CONTENTCOMPALGO:
                              num = ebml_read_uint (s, &lll);
                              if (num == EBML_UINT_INVALID)
                                goto err_out;
                              e.comp_algo = num;
                              break;

                            case MATROSKA_ID_CONTENTCOMPSETTINGS:
                              lll = ebml_read_length (s, &i);
			      if (lll == EBML_UINT_INVALID)
                                goto err_out;
                              e.comp_settings = (uint8_t*)malloc (lll);
                              read_data(s, e.comp_settings, lll);
                              e.comp_settings_len = lll;
                              lll += i;
                              break;

                            default:
                              ebml_read_skip (s, &lll);
                              break;
                            }
                          le -= lll + iiil;
                        }

                      if (e.type == 1)
                        {
                          mp_msg(MSGT_DEMUX, MSGL_WARN,
                                 MSGTR_MPDEMUX_MKV_TrackEncrypted, track->tnum);
                        }
                      else if (e.type != 0)
                        {
                          mp_msg(MSGT_DEMUX, MSGL_WARN,
                                 MSGTR_MPDEMUX_MKV_UnknownContentEncoding, track->tnum);
                        }

                      if (e.comp_algo != 0 && e.comp_algo != 2)
                        {
                          mp_msg (MSGT_DEMUX, MSGL_WARN,
                                  MSGTR_MPDEMUX_MKV_UnknownCompression,
                                  track->tnum, e.comp_algo);
                        }
#if !CONFIG_ZLIB
                      else if (e.comp_algo == 0)
                        {
                          mp_msg (MSGT_DEMUX, MSGL_WARN,
                                  MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported,
                                  track->tnum);
                        }
#endif

                      break;
                    }

                  default:
                    ebml_read_skip (s, &ll);
                    break;
                  }
                len -= ll + iil;
              }
            for (i=0; i<n; i++)
              if (e.order <= ce[i].order)
                break;
            ce = (mkv_content_encoding_t*)realloc (ce, (n+1) *sizeof (*ce));
            memmove (ce+i+1, ce+i, (n-i) * sizeof (*ce));
            memcpy (ce+i, &e, sizeof (e));
            n++;
            break;
          }

        default:
          ebml_read_skip (s, &l);
          break;
        }

      length -= l + il;
    }

  track->encodings = ce;
  track->num_encodings = n;
  return len;

err_out:
  demux_mkv_free_encodings(ce, n);
  return 0;
}
static int
demux_mkv_read_block(FILE *s, mkv_demuxer_t *mkv_d)
{
	uint64_t length, l;
	int il, tmp;
	uint64_t block_duration = 0,  block_length = 0;
	int64_t block_bref = 0, block_fref = 0;
	uint8_t *block = NULL;

	length = ebml_read_length (s, NULL);
	while (length > 0)
	{
		switch (ebml_read_id (s, &il))
		{
			case MATROSKA_ID_BLOCKDURATION:
				//puts("MATROSKA_ID_BLOCKDURATION");
				block_duration = ebml_read_uint (s, &l);
				if (block_duration == EBML_UINT_INVALID) {
					if(block)
						free(block);
					return 0;
				}
				block_duration *= mkv_d->tc_scale / 1000000.0;
				break;
			case MATROSKA_ID_BLOCK:
				//puts("MATROSKA_ID_BLOCK");
				block_length = ebml_read_length (s, &tmp);
				if(block)
					free(block);
				if (block_length > SIZE_MAX - AV_LZO_INPUT_PADDING) return 0;
				block = (uint8_t *)malloc (block_length + AV_LZO_INPUT_PADDING);
				if (!block)
				{
					return 0;
				}
				if (fread(block, 1, (size_t)block_length, s) != (size_t) block_length)
				{
					if(block)
						free(block);
					return 0;
				}
				l = tmp + block_length;
				break;
			case MATROSKA_ID_REFERENCEBLOCK:
				//puts("MATROSKA_ID_REFERENCEBLOCK");
				{
					int64_t num = ebml_read_int (s, &l);
					if (num == EBML_INT_INVALID) {
						if(block)
							free(block);
						return 0;
					}
					if (num <= 0)
						block_bref = num;
					else
						block_fref = num;
					break;
				}
			case EBML_ID_INVALID:
				//puts("EBML_ID_INVALID");
				if(block)
					free(block);
				return 0;
			default:
				ebml_read_skip (s, &l);
				break;
		}
		length -= l + il;

		if (block)
		{
			handle_block (mkv_d, block, block_length,
					block_duration, block_bref, block_fref, 0);
			free (block);
			block = NULL;
		}
	}
	return 0;
}
static int
demux_mkv_read_trackentry (FILE *s, mkv_demuxer_t *mkv_d)
{
  mkv_track_t *track;
  uint64_t len, length, l;
  int il;

  track = (mkv_track_t *)calloc (1, sizeof (*track));
  /* set default values */
  track->default_track = 1;
  track->name = 0;
  track->language = strdup("eng");

  len = length = ebml_read_length (s, &il);
  len += il;
  while (length > 0)
    {
      switch (ebml_read_id (s, &il))
        {
        case MATROSKA_ID_TRACKNUMBER:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              goto err_out;
            track->tnum = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Track number: %u\n",
                    track->tnum);
            break;
          }

        case MATROSKA_ID_TRACKNAME:
          {
            track->name = ebml_read_utf8 (s, &l);
            if (track->name == NULL)
              goto err_out;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Name: %s\n",
                    track->name);
            break;
          }

        case MATROSKA_ID_TRACKTYPE:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              goto err_out;
            track->type = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Track type: ");
            switch (track->type)
              {
              case MATROSKA_TRACK_AUDIO:
                mp_msg (MSGT_DEMUX, MSGL_V, "Audio\n");
                break;
              case MATROSKA_TRACK_VIDEO:
                mp_msg (MSGT_DEMUX, MSGL_V, "Video\n");
                break;
              case MATROSKA_TRACK_SUBTITLE:
                mp_msg (MSGT_DEMUX, MSGL_V, "Subtitle\n");
                break;
              default:
                mp_msg (MSGT_DEMUX, MSGL_V, "unknown\n");
                break;
            }
            break;
          }

        case MATROSKA_ID_TRACKAUDIO:
          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Audio track\n");
          l = demux_mkv_read_trackaudio (s, track);
          if (l == 0)
            goto err_out;
          break;

        case MATROSKA_ID_TRACKVIDEO:
          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Video track\n");
          l = demux_mkv_read_trackvideo (s, track);
          if (l == 0)
            goto err_out;
          break;

        case MATROSKA_ID_CODECID:
          track->codec_id = ebml_read_ascii (s, &l);
          if (track->codec_id == NULL)
            goto err_out;
          if (!strcmp (track->codec_id, MKV_V_MSCOMP) ||
              !strcmp (track->codec_id, MKV_A_ACM))
            track->ms_compat = 1;
          else if (!strcmp (track->codec_id, MKV_S_VOBSUB))
            track->subtitle_type = MATROSKA_SUBTYPE_VOBSUB;
          else if (!strcmp (track->codec_id, MKV_S_TEXTSSA)
                   || !strcmp (track->codec_id, MKV_S_TEXTASS)
                   || !strcmp (track->codec_id, MKV_S_SSA)
                   || !strcmp (track->codec_id, MKV_S_ASS))
            {
              track->subtitle_type = MATROSKA_SUBTYPE_SSA;
            }
          else if (!strcmp (track->codec_id, MKV_S_TEXTASCII))
            track->subtitle_type = MATROSKA_SUBTYPE_TEXT;
          if (!strcmp (track->codec_id, MKV_S_TEXTUTF8))
            {
              track->subtitle_type = MATROSKA_SUBTYPE_TEXT;
            }
          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Codec ID: %s\n",
                  track->codec_id);
          break;

        case MATROSKA_ID_CODECPRIVATE:
          {
            int x;
            uint64_t num = ebml_read_length (s, &x);
	    // audit: cheap guard against overflows later..
	    if (num > SIZE_MAX - 1000)
              goto err_out;
            l = x + num;
            track->private_data = malloc (num + AV_LZO_INPUT_PADDING);
            if (read_data(s, track->private_data, num) != (size_t) num)
              goto err_out;
            track->private_size = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + CodecPrivate, length "
                    "%u\n", track->private_size);
			if( track->type == MATROSKA_TRACK_VIDEO &&
					!strcmp(track->codec_id,MKV_V_MPEG4_AVC)
			  )
			{
				unsigned char*  ptr, *hdr;
				int write_len=0;
				int avc1_header_size = 0;

				ptr = (unsigned char *)track->private_data + 7; //skip 01 64 00 29 FF E1 00 and seek to first header len pos.

				unsigned char *avc1_header = (unsigned char *)malloc (track->private_size + AV_LZO_INPUT_PADDING);
				hdr = avc1_header;

				write_len = *ptr++; //get first header len

				hdr[0] = hdr[1] = hdr[2] = 0;
				hdr[3] = (unsigned char)write_len;
				hdr += 4;

				memcpy(hdr, ptr, write_len);
				hdr += write_len;
				ptr += write_len;

				avc1_header_size += 4 + write_len;

				mp_msg(MSGT_DEMUX, MSGL_V, "1write_len[%d]\n",write_len);//SkyMedi_Vincent

				ptr += 2;   //skip 01 00 and seek to second header len pos.
				write_len = *ptr++; //get second header len

				hdr[0] = hdr[1] = hdr[2] = 0;
				hdr[3] = (unsigned char)write_len;
				hdr += 4;

				memcpy(hdr, ptr, write_len);

				avc1_header_size += 4 + write_len;

				mp_msg(MSGT_DEMUX, MSGL_V, "2write_len[%d]\n",write_len);//SkyMedi_Vincent
				mp_msg(MSGT_DEMUX, MSGL_V, "avc1_header_size = %d\n", avc1_header_size);
				{
					int i = 0;
					for( i = 0 ; i< avc1_header_size; i++)
						mp_msg(MSGT_DEMUX, MSGL_V, "%02X ", avc1_header[i]);
					mp_msg(MSGT_DEMUX, MSGL_V, "\n");
				}

				if (!check_avc1_sps_bank0(avc1_header+5, avc1_header_size-5))
					goto err_out;

				free(avc1_header);
			}
            break;
          }

        case MATROSKA_ID_TRACKLANGUAGE:
          free(track->language);
          track->language = ebml_read_utf8 (s, &l);
          if (track->language == NULL)
            goto err_out;
          mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Language: %s\n",
                  track->language);
          break;

        case MATROSKA_ID_TRACKFLAGDEFAULT:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              goto err_out;
            track->default_track = num;
            mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Default flag: %u\n",
                    track->default_track);
            break;
          }

        case MATROSKA_ID_TRACKDEFAULTDURATION:
          {
            uint64_t num = ebml_read_uint (s, &l);
            if (num == EBML_UINT_INVALID)
              goto err_out;
            if (num == 0)
              mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Default duration: 0");
            else
              {
                track->v_frate = 1000000000.0 / num;
                track->default_duration = num / 1000000000.0;
                mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] |  + Default duration: "
                        "%.3fms ( = %.3f fps)\n",num/1000000.0,track->v_frate);
              }
            break;
          }

        case MATROSKA_ID_TRACKENCODINGS:
          l = demux_mkv_read_trackencodings (s, track);
          if (l == 0)
            goto err_out;
          break;

        default:
          ebml_read_skip (s, &l);
          break;
        }
      length -= l + il;
    }

  mkv_d->tracks[mkv_d->num_tracks++] = track;
  return len;

err_out:
  demux_mkv_free_trackentry(track);
  return 0;
}