📄 matroska.c
字号:
} /* read out length */ total &= ~len_mask; while (n++ < read) total = (total << 8) | get_byte(pb); *number = total; return read;}/* * Read: the element content data ID. * Return: the number of bytes read or < 0 on error. */static intebml_read_element_id (MatroskaDemuxContext *matroska, uint32_t *id, int *level_up){ int read; uint64_t total; /* if we re-call this, use our cached ID */ if (matroska->peek_id != 0) { if (level_up) *level_up = 0; *id = matroska->peek_id; return 0; } /* read out the "EBML number", include tag in ID */ if ((read = ebml_read_num(matroska, 4, &total)) < 0) return read; *id = matroska->peek_id = total | (1 << (read * 7)); /* level tracking */ if (level_up) *level_up = ebml_read_element_level_up(matroska); return read;}/* * Read: element content length. * Return: the number of bytes read or < 0 on error. */static intebml_read_element_length (MatroskaDemuxContext *matroska, uint64_t *length){ /* clear cache since we're now beyond that data point */ matroska->peek_id = 0; /* read out the "EBML number", include tag in ID */ return ebml_read_num(matroska, 8, length);}/* * Return: the ID of the next element, or 0 on error. * Level_up contains the amount of levels that this * next element lies higher than the previous one. */static uint32_tebml_peek_id (MatroskaDemuxContext *matroska, int *level_up){ uint32_t id; assert(level_up != NULL); if (ebml_read_element_id(matroska, &id, level_up) < 0) return 0; return id;}/* * Seek to a given offset. * 0 is success, -1 is failure. */static intebml_read_seek (MatroskaDemuxContext *matroska, offset_t offset){ ByteIOContext *pb = &matroska->ctx->pb; /* clear ID cache, if any */ matroska->peek_id = 0; return (url_fseek(pb, offset, SEEK_SET) == offset) ? 0 : -1;}/* * Skip the next element. * 0 is success, -1 is failure. */static intebml_read_skip (MatroskaDemuxContext *matroska){ ByteIOContext *pb = &matroska->ctx->pb; uint32_t id; uint64_t length; int res; if ((res = ebml_read_element_id(matroska, &id, NULL)) < 0 || (res = ebml_read_element_length(matroska, &length)) < 0) return res; url_fskip(pb, length); return 0;}/* * Read the next element as an unsigned int. * 0 is success, < 0 is failure. */static intebml_read_uint (MatroskaDemuxContext *matroska, uint32_t *id, uint64_t *num){ ByteIOContext *pb = &matroska->ctx->pb; int n = 0, size, res; uint64_t rlength; if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 || (res = ebml_read_element_length(matroska, &rlength)) < 0) return res; size = rlength; if (size < 1 || size > 8) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, "Invalid uint element size %d at position %"PRId64" (0x%"PRIx64")\n", size, pos, pos); return AVERROR_INVALIDDATA; } /* big-endian ordening; build up number */ *num = 0; while (n++ < size) *num = (*num << 8) | get_byte(pb); return 0;}/* * Read the next element as a signed int. * 0 is success, < 0 is failure. */static intebml_read_sint (MatroskaDemuxContext *matroska, uint32_t *id, int64_t *num){ ByteIOContext *pb = &matroska->ctx->pb; int size, n = 1, negative = 0, res; uint64_t rlength; if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 || (res = ebml_read_element_length(matroska, &rlength)) < 0) return res; size = rlength; if (size < 1 || size > 8) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, "Invalid sint element size %d at position %"PRId64" (0x%"PRIx64")\n", size, pos, pos); return AVERROR_INVALIDDATA; } if ((*num = get_byte(pb)) & 0x80) { negative = 1; *num &= ~0x80; } *num = 0; while (n++ < size) *num = (*num << 8) | get_byte(pb); /* make signed */ if (negative) *num = *num - (1LL << ((8 * size) - 1)); return 0;}/* * Read the next element as a float. * 0 is success, < 0 is failure. */static intebml_read_float (MatroskaDemuxContext *matroska, uint32_t *id, double *num){ ByteIOContext *pb = &matroska->ctx->pb; int size, res; uint64_t rlength; if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 || (res = ebml_read_element_length(matroska, &rlength)) < 0) return res; size = rlength; if (size == 4) { *num= av_int2flt(get_be32(pb)); } else if(size==8){ *num= av_int2dbl(get_be64(pb)); } else if(size==10){ av_log(matroska->ctx, AV_LOG_ERROR, "FIXME! 10-byte floats unimplemented\n"); return AVERROR_UNKNOWN; } else{ offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, "Invalid float element size %d at position %"PRIu64" (0x%"PRIx64")\n", size, pos, pos); return AVERROR_INVALIDDATA; } return 0;}/* * Read the next element as an ASCII string. * 0 is success, < 0 is failure. */static intebml_read_ascii (MatroskaDemuxContext *matroska, uint32_t *id, char **str){ ByteIOContext *pb = &matroska->ctx->pb; int size, res; uint64_t rlength; if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 || (res = ebml_read_element_length(matroska, &rlength)) < 0) return res; size = rlength; /* ebml strings are usually not 0-terminated, so we allocate one * byte more, read the string and NULL-terminate it ourselves. */ if (size < 0 || !(*str = av_malloc(size + 1))) { av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation failed\n"); return AVERROR_NOMEM; } if (get_buffer(pb, (uint8_t *) *str, size) != size) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos); return AVERROR_IO; } (*str)[size] = '\0'; return 0;}/* * Read the next element as a UTF-8 string. * 0 is success, < 0 is failure. */static intebml_read_utf8 (MatroskaDemuxContext *matroska, uint32_t *id, char **str){ return ebml_read_ascii(matroska, id, str);}/* * Read the next element as a date (nanoseconds since 1/1/2000). * 0 is success, < 0 is failure. */static intebml_read_date (MatroskaDemuxContext *matroska, uint32_t *id, int64_t *date){ return ebml_read_sint(matroska, id, date);}/* * Read the next element, but only the header. The contents * are supposed to be sub-elements which can be read separately. * 0 is success, < 0 is failure. */static intebml_read_master (MatroskaDemuxContext *matroska, uint32_t *id){ ByteIOContext *pb = &matroska->ctx->pb; uint64_t length; MatroskaLevel *level; int res; if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 || (res = ebml_read_element_length(matroska, &length)) < 0) return res; /* protect... (Heaven forbids that the '>' is true) */ if (matroska->num_levels >= EBML_MAX_DEPTH) { av_log(matroska->ctx, AV_LOG_ERROR, "File moves beyond max. allowed depth (%d)\n", EBML_MAX_DEPTH); return AVERROR_NOTSUPP; } /* remember level */ level = &matroska->levels[matroska->num_levels++]; level->start = url_ftell(pb); level->length = length; return 0;}/* * Read the next element as binary data. * 0 is success, < 0 is failure. */static intebml_read_binary (MatroskaDemuxContext *matroska, uint32_t *id, uint8_t **binary, int *size){ ByteIOContext *pb = &matroska->ctx->pb; uint64_t rlength; int res; if ((res = ebml_read_element_id(matroska, id, NULL)) < 0 || (res = ebml_read_element_length(matroska, &rlength)) < 0) return res; *size = rlength; if (!(*binary = av_malloc(*size))) { av_log(matroska->ctx, AV_LOG_ERROR, "Memory allocation error\n"); return AVERROR_NOMEM; } if (get_buffer(pb, *binary, *size) != *size) { offset_t pos = url_ftell(pb); av_log(matroska->ctx, AV_LOG_ERROR, "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos); return AVERROR_IO; } return 0;}/* * Read signed/unsigned "EBML" numbers. * Return: number of bytes processed, < 0 on error. * XXX: use ebml_read_num(). */static intmatroska_ebmlnum_uint (uint8_t *data, uint32_t size, uint64_t *num){ int len_mask = 0x80, read = 1, n = 1, num_ffs = 0; uint64_t total; if (size <= 0) return AVERROR_INVALIDDATA; total = data[0]; while (read <= 8 && !(total & len_mask)) { read++; len_mask >>= 1; } if (read > 8) return AVERROR_INVALIDDATA; if ((total &= (len_mask - 1)) == len_mask - 1) num_ffs++; if (size < read) return AVERROR_INVALIDDATA; while (n < read) { if (data[n] == 0xff) num_ffs++; total = (total << 8) | data[n]; n++; } if (read == num_ffs) *num = (uint64_t)-1; else *num = total; return read;}/* * Same as above, but signed. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -