📄 demux_mkv.c
字号:
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); length = ebml_read_length (s, NULL); while (length > 0) { switch (ebml_read_id (s, &il)) { case MATROSKA_ID_EDITIONENTRY: { uint64_t len; int i; len = ebml_read_length (s, &i); l = len + i; while (len > 0) { uint64_t l; int il; switch (ebml_read_id (s, &il)) { case MATROSKA_ID_CHAPTERATOM: { uint64_t len, start=0, end=0; int i; len = ebml_read_length (s, &i); l = len + i; if (mkv_d->chapters == NULL) mkv_d->chapters = malloc (32*sizeof(*mkv_d->chapters)); else if (!(mkv_d->num_chapters % 32)) mkv_d->chapters = realloc (mkv_d->chapters, (mkv_d->num_chapters + 32) * sizeof(*mkv_d->chapters)); while (len > 0) { uint64_t l; int il; switch (ebml_read_id (s, &il)) { case MATROSKA_ID_CHAPTERTIMESTART: start = ebml_read_uint (s, &l) / 1000000; break; case MATROSKA_ID_CHAPTERTIMEEND: end = ebml_read_uint (s, &l) / 1000000; break; default: ebml_read_skip (s, &l); break; } len -= l + il; } mkv_d->chapters[mkv_d->num_chapters].start = start; mkv_d->chapters[mkv_d->num_chapters].end = end; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter %u from %02d:%02d:%02d." "%03d to %02d:%02d:%02d.%03d\n", ++mkv_d->num_chapters, (int) (start / 60 / 60 / 1000), (int) ((start / 60 / 1000) % 60), (int) ((start / 1000) % 60), (int) (start % 1000), (int) (end / 60 / 60 / 1000), (int) ((end / 60 / 1000) % 60), (int) ((end / 1000) % 60), (int) (end % 1000)); break; } default: ebml_read_skip (s, &l); break; } len -= l + il; } break; } default: ebml_read_skip (s, &l); break; } length -= l + il; } mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing chapters ] ---------\n"); return 0;}static intdemux_mkv_read_tags (demuxer_t *demuxer){ ebml_read_skip (demuxer->stream, NULL); return 0;}static intdemux_mkv_read_seekhead (demuxer_t *demuxer){ mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; uint64_t length, l, seek_pos, saved_pos, num; uint32_t seek_id; int i, il, res = 0; off_t off; off = stream_tell (s); for (i=0; i<mkv_d->parsed_seekhead_num; i++) if (mkv_d->parsed_seekhead[i] == off) { ebml_read_skip (s, NULL); return 0; } mkv_d->parsed_seekhead = (off_t *) realloc (mkv_d->parsed_seekhead, (mkv_d->parsed_seekhead_num+1) * sizeof (off_t)); mkv_d->parsed_seekhead[mkv_d->parsed_seekhead_num++] = off; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing seek head ] ---------\n"); length = ebml_read_length (s, NULL); while (length > 0 && !res) { seek_id = 0; seek_pos = EBML_UINT_INVALID; switch (ebml_read_id (s, &il)) { case MATROSKA_ID_SEEKENTRY: { uint64_t len; len = ebml_read_length (s, &i); l = len + i; while (len > 0) { uint64_t l; int il; switch (ebml_read_id (s, &il)) { case MATROSKA_ID_SEEKID: num = ebml_read_uint (s, &l); if (num != EBML_UINT_INVALID) seek_id = num; break; case MATROSKA_ID_SEEKPOSITION: seek_pos = ebml_read_uint (s, &l); break; default: ebml_read_skip (s, &l); break; } len -= l + il; } break; } default: ebml_read_skip (s, &l); break; } length -= l + il; if (seek_id == 0 || seek_id == MATROSKA_ID_CLUSTER || seek_pos == EBML_UINT_INVALID || ((mkv_d->segment_start + seek_pos) >= (uint64_t)demuxer->movi_end)) continue; saved_pos = stream_tell (s); if (!stream_seek (s, mkv_d->segment_start + seek_pos)) res = 1; else { if (ebml_read_id (s, &il) != seek_id) res = 1; else switch (seek_id) { case MATROSKA_ID_CUES: if (demux_mkv_read_cues (demuxer)) res = 1; break; case MATROSKA_ID_TAGS: if (demux_mkv_read_tags (demuxer)) res = 1; break; case MATROSKA_ID_SEEKHEAD: if (demux_mkv_read_seekhead (demuxer)) res = 1; break; case MATROSKA_ID_CHAPTERS: if (demux_mkv_read_chapters (demuxer)) res = 1; break; } } stream_seek (s, saved_pos); } if (length > 0) stream_seek (s, stream_tell (s) + length); mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing seek head ] ---------\n"); return res;}static voiddisplay_tracks (mkv_demuxer_t *mkv_d){ int i, vid=0, aid=0, sid=0; for (i=0; i<mkv_d->num_tracks; i++) { char *type = "unknown", str[32]; *str = '\0'; switch (mkv_d->tracks[i]->type) { case MATROSKA_TRACK_VIDEO: type = "video"; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VIDEO_ID=%d\n", vid); sprintf (str, "-vid %u", vid++); break; case MATROSKA_TRACK_AUDIO: type = "audio"; if (identify) { mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AUDIO_ID=%d\n", aid); mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AID_%d_LANG=%s\n", aid, mkv_d->tracks[i]->language); } sprintf (str, "-aid %u, -alang %.5s",aid++,mkv_d->tracks[i]->language); break; case MATROSKA_TRACK_SUBTITLE: type = "subtitles"; if (identify) { mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid); mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, mkv_d->tracks[i]->language); } sprintf (str, "-sid %u, -slang %.5s",sid++,mkv_d->tracks[i]->language); break; } mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] Track ID %u: %s (%s), %s\n", mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id, str); }}static intdemux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track){ BITMAPINFOHEADER *bih; void *ImageDesc = NULL; sh_video_t *sh_v; if (track->ms_compat) /* MS compatibility mode */ { BITMAPINFOHEADER *src; if (track->private_data == NULL || track->private_size < sizeof (BITMAPINFOHEADER)) return 1; src = (BITMAPINFOHEADER *) track->private_data; bih = (BITMAPINFOHEADER *) malloc (track->private_size); memset (bih, 0, track->private_size); bih->biSize = le2me_32 (src->biSize); bih->biWidth = le2me_32 (src->biWidth); bih->biHeight = le2me_32 (src->biHeight); bih->biPlanes = le2me_16 (src->biPlanes); bih->biBitCount = le2me_16 (src->biBitCount); bih->biCompression = le2me_32 (src->biCompression); bih->biSizeImage = le2me_32 (src->biSizeImage); bih->biXPelsPerMeter = le2me_32 (src->biXPelsPerMeter); bih->biYPelsPerMeter = le2me_32 (src->biYPelsPerMeter); bih->biClrUsed = le2me_32 (src->biClrUsed); bih->biClrImportant = le2me_32 (src->biClrImportant); memcpy((char *) bih + sizeof (BITMAPINFOHEADER), (char *) src + sizeof (BITMAPINFOHEADER), track->private_size - sizeof (BITMAPINFOHEADER)); if (track->v_width == 0) track->v_width = bih->biWidth; if (track->v_height == 0) track->v_height = bih->biHeight; } else { bih = (BITMAPINFOHEADER *) malloc (sizeof (BITMAPINFOHEADER)); memset (bih, 0, sizeof (BITMAPINFOHEADER)); bih->biSize = sizeof (BITMAPINFOHEADER); bih->biWidth = track->v_width; bih->biHeight = track->v_height; bih->biBitCount = 24; bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; if (track->private_size >= sizeof (real_video_props_t) && (!strcmp (track->codec_id, MKV_V_REALV10) || !strcmp (track->codec_id, MKV_V_REALV20) || !strcmp (track->codec_id, MKV_V_REALV30) || !strcmp (track->codec_id, MKV_V_REALV40))) { unsigned char *dst, *src; real_video_props_t *rvp; uint32_t type2; rvp = (real_video_props_t *) track->private_data; src = (unsigned char *) (rvp + 1); bih = (BITMAPINFOHEADER *) realloc(bih, sizeof (BITMAPINFOHEADER)+12); bih->biSize = 48; bih->biPlanes = 1; type2 = be2me_32 (rvp->type2); if (type2 == 0x10003000 || type2 == 0x10003001) bih->biCompression=mmioFOURCC('R','V','1','3'); else bih->biCompression=mmioFOURCC('R','V',track->codec_id[9],'0'); dst = (unsigned char *) (bih + 1); ((unsigned int *) dst)[0] = be2me_32 (rvp->type1); ((unsigned int *) dst)[1] = type2; if (bih->biCompression <= 0x30335652 && type2 >= 0x20200002) { /* read secondary WxH for the cmsg24[] (see vd_realvid.c) */ ((unsigned short *)(bih+1))[4] = 4 * (unsigned short) src[0]; ((unsigned short *)(bih+1))[5] = 4 * (unsigned short) src[1]; } else memset(&dst[8], 0, 4); track->realmedia = 1;#ifdef USE_QTX_CODECS } else if (track->private_size >= sizeof (ImageDescription) && !strcmp(track->codec_id, MKV_V_QUICKTIME)) { ImageDescriptionPtr idesc; idesc = (ImageDescriptionPtr) track->private_data; idesc->idSize = be2me_32 (idesc->idSize); idesc->cType = be2me_32 (idesc->cType); idesc->version = be2me_16 (idesc->version); idesc->revisionLevel = be2me_16 (idesc->revisionLevel); idesc->vendor = be2me_32 (idesc->vendor); idesc->temporalQuality = be2me_32 (idesc->temporalQuality); idesc->spatialQuality = be2me_32 (idesc->spatialQuality); idesc->width = be2me_16 (idesc->width); idesc->height = be2me_16 (idesc->height); idesc->hRes = be2me_32 (idesc->hRes); idesc->vRes = be2me_32 (idesc->vRes); idesc->dataSize = be2me_32 (idesc->dataSize); idesc->frameCount = be2me_16 (idesc->frameCount); idesc->depth = be2me_16 (idesc->depth); idesc->clutID = be2me_16 (idesc->clutID); bih->biPlanes = 1; bih->biCompression = idesc->cType; ImageDesc = idesc;#endif /* USE_QTX_CODECS */ } else if (!strcmp(track->codec_id, MKV_V_MPEG1)) { bih->biCompression = mmioFOURCC('m', 'p', 'g', '1'); track->reorder_timecodes = 1; } else if (!strcmp(track->codec_id, MKV_V_MPEG2)) { bih->biCompression = mmioFOURCC('m', 'p', 'g', '2'); track->reorder_timecodes = 1; } else if (!strcmp(track->codec_id, MKV_V_MPEG4_AVC)) { bih->biCompression = mmioFOURCC('a', 'v', 'c', '1'); if (track->private_data && (track->private_size > 0)) { bih->biSize += track->private_size; bih = (BITMAPINFOHEADER *) realloc (bih, bih->biSize); memcpy (bih + 1, track->private_data, track->private_size); } track->reorder_timecodes = 1; } else { mp_msg (MSGT_DEMUX,MSGL_WARN,"[mkv] Unknown/unsupported CodecID " "(%s) or missing/bad CodecPrivate data (track %u).\n", track->codec_id, track->tnum); free(bih); return 1; } } sh_v = new_sh_video (demuxer, track->tnum); sh_v->bih = bih; sh_v->format = sh_v->bih->biCompression; if (track->v_frate == 0.0) track->v_frate = 25.0; sh_v->fps = track->v_frate; sh_v->frametime = 1 / track->v_frate; sh_v->aspect = 0; if (!track->realmedia) { sh_v->disp_w = track->v_width; sh_v->disp_h = track->v_height; if (track->v_dheight) sh_v->aspect = (float)track->v_dwidth / (float)track->v_dheight; } else { // vd_realvid.c will set aspect to disp_w/disp_h and rederive // disp_w and disp_h from the RealVideo stream contents returned // by the Real DLLs. If DisplayWidth/DisplayHeight was not set in // the Matroska file then it has already been set to PixelWidth/Height // by check_track_information. sh_v->disp_w = track->v_dwidth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -