📄 matroskadec.c
字号:
/* * Put a packet into our internal queue. Will be delivered to the * user/application during the next get_packet() call. */static voidmatroska_queue_packet (MatroskaDemuxContext *matroska, AVPacket *pkt){ matroska->packets = av_realloc(matroska->packets, (matroska->num_packets + 1) * sizeof(AVPacket *)); matroska->packets[matroska->num_packets] = pkt; matroska->num_packets++;}/* * Free all packets in our internal queue. */static voidmatroska_clear_queue (MatroskaDemuxContext *matroska){ if (matroska->packets) { int n; for (n = 0; n < matroska->num_packets; n++) { av_free_packet(matroska->packets[n]); av_free(matroska->packets[n]); } av_free(matroska->packets); matroska->packets = NULL; matroska->num_packets = 0; }}/* * Autodetecting... */static intmatroska_probe (AVProbeData *p){ uint64_t total = 0; int len_mask = 0x80, size = 1, n = 1; uint8_t probe_data[] = { 'm', 'a', 't', 'r', 'o', 's', 'k', 'a' }; /* ebml header? */ if (AV_RB32(p->buf) != EBML_ID_HEADER) return 0; /* length of header */ total = p->buf[4]; while (size <= 8 && !(total & len_mask)) { size++; len_mask >>= 1; } if (size > 8) return 0; total &= (len_mask - 1); while (n < size) total = (total << 8) | p->buf[4 + n++]; /* does the probe data contain the whole header? */ if (p->buf_size < 4 + size + total) return 0; /* the header must contain the document type 'matroska'. For now, * we don't parse the whole header but simply check for the * availability of that array of characters inside the header. * Not fully fool-proof, but good enough. */ for (n = 4 + size; n <= 4 + size + total - sizeof(probe_data); n++) if (!memcmp (&p->buf[n], probe_data, sizeof(probe_data))) return AVPROBE_SCORE_MAX; return 0;}/* * From here on, it's all XML-style DTD stuff... Needs no comments. */static intmatroska_parse_info (MatroskaDemuxContext *matroska){ int res = 0; uint32_t id; av_log(matroska->ctx, AV_LOG_DEBUG, "Parsing info...\n"); while (res == 0) { if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { res = AVERROR(EIO); break; } else if (matroska->level_up) { matroska->level_up--; break; } switch (id) { /* cluster timecode */ case MATROSKA_ID_TIMECODESCALE: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; matroska->time_scale = num; break; } case MATROSKA_ID_DURATION: { double num; if ((res = ebml_read_float(matroska, &id, &num)) < 0) break; matroska->ctx->duration = num * matroska->time_scale * 1000 / AV_TIME_BASE; break; } case MATROSKA_ID_TITLE: { char *text; if ((res = ebml_read_utf8(matroska, &id, &text)) < 0) break; strncpy(matroska->ctx->title, text, sizeof(matroska->ctx->title)-1); av_free(text); break; } case MATROSKA_ID_WRITINGAPP: { char *text; if ((res = ebml_read_utf8(matroska, &id, &text)) < 0) break; matroska->writing_app = text; break; } case MATROSKA_ID_MUXINGAPP: { char *text; if ((res = ebml_read_utf8(matroska, &id, &text)) < 0) break; matroska->muxing_app = text; break; } case MATROSKA_ID_DATEUTC: { int64_t time; if ((res = ebml_read_date(matroska, &id, &time)) < 0) break; matroska->created = time; break; } default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%x in info header\n", id); /* fall-through */ case EBML_ID_VOID: res = ebml_read_skip(matroska); break; } if (matroska->level_up) { matroska->level_up--; break; } } return res;}static intmatroska_add_stream (MatroskaDemuxContext *matroska){ int res = 0; uint32_t id; MatroskaTrack *track; av_log(matroska->ctx, AV_LOG_DEBUG, "parsing track, adding stream..,\n"); /* Allocate a generic track. As soon as we know its type we'll realloc. */ track = av_mallocz(MAX_TRACK_SIZE); matroska->num_tracks++; strcpy(track->language, "eng"); /* start with the master */ if ((res = ebml_read_master(matroska, &id)) < 0) return res; /* try reading the trackentry headers */ while (res == 0) { if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { res = AVERROR(EIO); break; } else if (matroska->level_up > 0) { matroska->level_up--; break; } switch (id) { /* track number (unique stream ID) */ case MATROSKA_ID_TRACKNUMBER: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; track->num = num; break; } /* track UID (unique identifier) */ case MATROSKA_ID_TRACKUID: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; track->uid = num; break; } /* track type (video, audio, combined, subtitle, etc.) */ case MATROSKA_ID_TRACKTYPE: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; if (track->type && track->type != num) { av_log(matroska->ctx, AV_LOG_INFO, "More than one tracktype in an entry - skip\n"); break; } track->type = num; switch (track->type) { case MATROSKA_TRACK_TYPE_VIDEO: case MATROSKA_TRACK_TYPE_AUDIO: case MATROSKA_TRACK_TYPE_SUBTITLE: break; case MATROSKA_TRACK_TYPE_COMPLEX: case MATROSKA_TRACK_TYPE_LOGO: case MATROSKA_TRACK_TYPE_CONTROL: default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown or unsupported track type 0x%x\n", track->type); track->type = 0; break; } matroska->tracks[matroska->num_tracks - 1] = track; break; } /* tracktype specific stuff for video */ case MATROSKA_ID_TRACKVIDEO: { MatroskaVideoTrack *videotrack; if (!track->type) track->type = MATROSKA_TRACK_TYPE_VIDEO; if (track->type != MATROSKA_TRACK_TYPE_VIDEO) { av_log(matroska->ctx, AV_LOG_INFO, "video data in non-video track - ignoring\n"); res = AVERROR_INVALIDDATA; break; } else if ((res = ebml_read_master(matroska, &id)) < 0) break; videotrack = (MatroskaVideoTrack *)track; while (res == 0) { if (!(id = ebml_peek_id(matroska, &matroska->level_up))) { res = AVERROR(EIO); break; } else if (matroska->level_up > 0) { matroska->level_up--; break; } switch (id) { /* fixme, this should be one-up, but I get it here */ case MATROSKA_ID_TRACKDEFAULTDURATION: { uint64_t num; if ((res = ebml_read_uint (matroska, &id, &num)) < 0) break; track->default_duration = num; break; } /* video framerate */ case MATROSKA_ID_VIDEOFRAMERATE: { double num; if ((res = ebml_read_float(matroska, &id, &num)) < 0) break; if (!track->default_duration) track->default_duration = 1000000000/num; break; } /* width of the size to display the video at */ case MATROSKA_ID_VIDEODISPLAYWIDTH: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; videotrack->display_width = num; break; } /* height of the size to display the video at */ case MATROSKA_ID_VIDEODISPLAYHEIGHT: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; videotrack->display_height = num; break; } /* width of the video in the file */ case MATROSKA_ID_VIDEOPIXELWIDTH: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; videotrack->pixel_width = num; break; } /* height of the video in the file */ case MATROSKA_ID_VIDEOPIXELHEIGHT: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; videotrack->pixel_height = num; break; } /* whether the video is interlaced */ case MATROSKA_ID_VIDEOFLAGINTERLACED: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; if (num) track->flags |= MATROSKA_VIDEOTRACK_INTERLACED; else track->flags &= ~MATROSKA_VIDEOTRACK_INTERLACED; break; } /* stereo mode (whether the video has two streams, * where one is for the left eye and the other for * the right eye, which creates a 3D-like * effect) */ case MATROSKA_ID_VIDEOSTEREOMODE: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; if (num != MATROSKA_EYE_MODE_MONO && num != MATROSKA_EYE_MODE_LEFT && num != MATROSKA_EYE_MODE_RIGHT && num != MATROSKA_EYE_MODE_BOTH) { av_log(matroska->ctx, AV_LOG_INFO, "Ignoring unknown eye mode 0x%x\n", (uint32_t) num); break; } videotrack->eye_mode = num; break; } /* aspect ratio behaviour */ case MATROSKA_ID_VIDEOASPECTRATIO: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; if (num != MATROSKA_ASPECT_RATIO_MODE_FREE && num != MATROSKA_ASPECT_RATIO_MODE_KEEP && num != MATROSKA_ASPECT_RATIO_MODE_FIXED) { av_log(matroska->ctx, AV_LOG_INFO, "Ignoring unknown aspect ratio 0x%x\n", (uint32_t) num); break; } videotrack->ar_mode = num; break; } /* colorspace (only matters for raw video) * fourcc */ case MATROSKA_ID_VIDEOCOLORSPACE: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) break; videotrack->fourcc = num; break; } default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown video track header entry " "0x%x - ignoring\n", id); /* pass-through */ case EBML_ID_VOID: res = ebml_read_skip(matroska); break; } if (matroska->level_up) { matroska->level_up--; break; } } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -