char *ebml_alloc_read_ascii (ebml_parser_t *ebml, ebml_elem_t *elem) { char *text; if (elem->len >= 4096) return NULL; text = malloc(elem->len + 1); if (text) { text[elem->len] = '\0'; if (ebml_read_ascii (ebml, elem, text)) return text; free (text); } return NULL; }
/* * Read the next element as a UTF-8 string. */ char *ebml_read_utf8(stream_t *s, uint64_t *length) { return ebml_read_ascii(s, length); }
/* * Read an EBML header. */ char *ebml_read_header(stream_t *s, int *version) { uint64_t length, l, num; uint32_t id; char *str = NULL; if (ebml_read_master(s, &length) != EBML_ID_HEADER) return 0; if (version) *version = 1; while (length > 0) { id = ebml_read_id(s, NULL); if (id == EBML_ID_INVALID) return NULL; length -= 2; switch (id) { /* is our read version uptodate? */ case EBML_ID_EBMLREADVERSION: num = ebml_read_uint(s, &l); if (num != EBML_VERSION) return NULL; break; /* we only handle 8 byte lengths at max */ case EBML_ID_EBMLMAXSIZELENGTH: num = ebml_read_uint(s, &l); if (num != sizeof(uint64_t)) return NULL; break; /* we handle 4 byte IDs at max */ case EBML_ID_EBMLMAXIDLENGTH: num = ebml_read_uint(s, &l); if (num != sizeof(uint32_t)) return NULL; break; case EBML_ID_DOCTYPE: str = ebml_read_ascii(s, &l); if (str == NULL) return NULL; break; case EBML_ID_DOCTYPEREADVERSION: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return NULL; if (version) *version = num; break; /* we ignore these two, they don't tell us anything we care about */ case EBML_ID_VOID: case EBML_ID_EBMLVERSION: case EBML_ID_DOCTYPEVERSION: default: if (ebml_read_skip(s, &l)) return NULL; break; } length -= l; } return str; }
int ebml_read_utf8 (ebml_parser_t *ebml, ebml_elem_t *elem, char *str) { return ebml_read_ascii (ebml, elem, str); }
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; }