demux_mkv.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,147 行 · 第 1/5 页
C
2,147 行
static intdemux_mkv_read_trackvideo (demuxer_t *demuxer, mkv_track_t *track){ stream_t *s = demuxer->stream; 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;}/** * \brief free any data associated with given track * \param track track of which to free data */static voiddemux_mkv_free_trackentry(mkv_track_t *track) { if (track->name) free (track->name); if (track->codec_id) free (track->codec_id); if (track->language) free (track->language); if (track->private_data) free (track->private_data); if (track->audio_buf) free (track->audio_buf); if (track->audio_timestamp) free (track->audio_timestamp);#ifdef USE_ASS if (track->sh_sub && track->sh_sub->ass_track) ass_free_track (track->sh_sub->ass_track);#endif demux_mkv_free_encodings(track->encodings, track->num_encodings); free(track);}static intdemux_mkv_read_trackentry (demuxer_t *demuxer){ mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; mkv_track_t *track; uint64_t len, length, l; int il; track = 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) return 0; 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 (demuxer, 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 (demuxer, 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) return 0; l = x + num; track->private_data = malloc (num + LZO_INPUT_PADDING); if (stream_read(s, track->private_data, num) != (int) num) goto err_out; track->private_size = num; mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + CodecPrivate, length " "%u\n", track->private_size); 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 (demuxer, 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;}static intdemux_mkv_read_tracks (demuxer_t *demuxer){ mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; uint64_t length, l; int il; mkv_d->tracks = 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 = realloc (mkv_d->tracks, (mkv_d->num_tracks+1) *sizeof (*mkv_d->tracks)); l = demux_mkv_read_trackentry (demuxer); if (l == 0) return 1; break; default: ebml_read_skip (s, &l); break; } length -= l + il; } return 0;}static intdemux_mkv_read_cues (demuxer_t *demuxer){ mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; uint64_t length, l, time, track, pos; off_t off; int i, il; if (index_mode == 0) { ebml_read_skip (s, NULL); return 0; } off = stream_tell (s); for (i=0; i<mkv_d->parsed_cues_num; i++) if (mkv_d->parsed_cues[i] == off) { ebml_read_skip (s, NULL); return 0; } mkv_d->parsed_cues = realloc (mkv_d->parsed_cues, (mkv_d->parsed_cues_num+1) * sizeof (off_t)); mkv_d->parsed_cues[mkv_d->parsed_cues_num++] = off; mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing cues ] -----------\n"); length = ebml_read_length (s, NULL); while (length > 0) { time = track = pos = EBML_UINT_INVALID; switch (ebml_read_id (s, &il)) { case MATROSKA_ID_POINTENTRY: { 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_CUETIME: time = ebml_read_uint (s, &l); break; case MATROSKA_ID_CUETRACKPOSITION: { uint64_t le; le = ebml_read_length (s, &i); l = le + i; while (le > 0) { uint64_t l; int il; switch (ebml_read_id (s, &il)) { case MATROSKA_ID_CUETRACK: track = ebml_read_uint (s, &l); break; case MATROSKA_ID_CUECLUSTERPOSITION: pos = ebml_read_uint (s, &l); break; default: ebml_read_skip (s, &l); break; } le -= l + il; } break; } default: ebml_read_skip (s, &l); break; } len -= l + il; } break; } default: ebml_read_skip (s, &l); break; } length -= l + il; if (time != EBML_UINT_INVALID && track != EBML_UINT_INVALID && pos != EBML_UINT_INVALID) { grow_array(&mkv_d->indexes, mkv_d->num_indexes, sizeof(mkv_index_t)); mkv_d->indexes[mkv_d->num_indexes].tnum = track; mkv_d->indexes[mkv_d->num_indexes].timecode = time; mkv_d->indexes[mkv_d->num_indexes].filepos =mkv_d->segment_start+pos; mp_msg (MSGT_DEMUX, MSGL_DBG2, "[mkv] |+ found cue point " "for track %"PRIu64": timecode %"PRIu64", filepos: %"PRIu64"\n", track, time, mkv_d->segment_start + pos);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?