📄 matroskadec.c
字号:
negative = 1; *num &= ~0x80; } 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{ 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(ENOMEM); } 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(EIO); } (*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(ENOSYS); } /* 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(ENOMEM); } 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(EIO); } 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. */static intmatroska_ebmlnum_sint (uint8_t *data, uint32_t size, int64_t *num){ uint64_t unum; int res; /* read as unsigned number first */ if ((res = matroska_ebmlnum_uint(data, size, &unum)) < 0) return res; /* make signed (weird way) */ if (unum == (uint64_t)-1) *num = INT64_MAX; else *num = unum - ((1LL << ((7 * res) - 1)) - 1); return res;}/* * Read an EBML header. * 0 is success, < 0 is failure. */static intebml_read_header (MatroskaDemuxContext *matroska, char **doctype, int *version){ uint32_t id; int level_up, res = 0; /* default init */ if (doctype) *doctype = NULL; if (version) *version = 1; if (!(id = ebml_peek_id(matroska, &level_up)) || level_up != 0 || id != EBML_ID_HEADER) { av_log(matroska->ctx, AV_LOG_ERROR, "This is not an EBML file (id=0x%x/0x%x)\n", id, EBML_ID_HEADER); return AVERROR_INVALIDDATA; } if ((res = ebml_read_master(matroska, &id)) < 0) return res; while (res == 0) { if (!(id = ebml_peek_id(matroska, &level_up))) return AVERROR(EIO); /* end-of-header */ if (level_up) break; switch (id) { /* is our read version uptodate? */ case EBML_ID_EBMLREADVERSION: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) return res; if (num > EBML_VERSION) { av_log(matroska->ctx, AV_LOG_ERROR, "EBML version %"PRIu64" (> %d) is not supported\n", num, EBML_VERSION); return AVERROR_INVALIDDATA; } break; } /* we only handle 8 byte lengths at max */ case EBML_ID_EBMLMAXSIZELENGTH: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) return res; if (num > sizeof(uint64_t)) { av_log(matroska->ctx, AV_LOG_ERROR, "Integers of size %"PRIu64" (> %zd) not supported\n", num, sizeof(uint64_t)); return AVERROR_INVALIDDATA; } break; } /* we handle 4 byte IDs at max */ case EBML_ID_EBMLMAXIDLENGTH: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) return res; if (num > sizeof(uint32_t)) { av_log(matroska->ctx, AV_LOG_ERROR, "IDs of size %"PRIu64" (> %zu) not supported\n", num, sizeof(uint32_t)); return AVERROR_INVALIDDATA; } break; } case EBML_ID_DOCTYPE: { char *text; if ((res = ebml_read_ascii(matroska, &id, &text)) < 0) return res; if (doctype) { if (*doctype) av_free(*doctype); *doctype = text; } else av_free(text); break; } case EBML_ID_DOCTYPEREADVERSION: { uint64_t num; if ((res = ebml_read_uint(matroska, &id, &num)) < 0) return res; if (version) *version = num; break; } default: av_log(matroska->ctx, AV_LOG_INFO, "Unknown data type 0x%x in EBML header", id); /* pass-through */ case EBML_ID_VOID: /* we ignore these two, as they don't tell us anything we * care about */ case EBML_ID_EBMLVERSION: case EBML_ID_DOCTYPEVERSION: res = ebml_read_skip (matroska); break; } } return 0;}static intmatroska_find_track_by_num (MatroskaDemuxContext *matroska, int num){ int i; for (i = 0; i < matroska->num_tracks; i++) if (matroska->tracks[i]->num == num) return i; return -1;}/* * Put one packet in an application-supplied AVPacket struct. * Returns 0 on success or -1 on failure. */static intmatroska_deliver_packet (MatroskaDemuxContext *matroska, AVPacket *pkt){ if (matroska->num_packets > 0) { memcpy(pkt, matroska->packets[0], sizeof(AVPacket)); av_free(matroska->packets[0]); if (matroska->num_packets > 1) { memmove(&matroska->packets[0], &matroska->packets[1], (matroska->num_packets - 1) * sizeof(AVPacket *)); matroska->packets = av_realloc(matroska->packets, (matroska->num_packets - 1) * sizeof(AVPacket *)); } else { av_freep(&matroska->packets); } matroska->num_packets--; return 0; } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -