diff options
author | Aurelien Jacobs <aurel@gnuage.org> | 2008-08-05 00:42:39 +0000 |
---|---|---|
committer | Aurelien Jacobs <aurel@gnuage.org> | 2008-08-05 00:42:39 +0000 |
commit | 737c40da20de07fd1b1ca99699f896c84b03f0ff (patch) | |
tree | 06d50219d1ac1eb87d39afb4c840c46503e98b07 | |
parent | 1b6d23bbcbeb3bdb44747275295b92495c89ab6d (diff) | |
download | ffmpeg-737c40da20de07fd1b1ca99699f896c84b03f0ff.tar.gz |
matroskadec: reorder some functions in a more logical order
Originally committed as revision 14604 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavformat/matroskadec.c | 328 |
1 files changed, 162 insertions, 166 deletions
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 13508b08c9..4cdeb527e0 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -595,6 +595,24 @@ static int ebml_read_ascii(ByteIOContext *pb, int size, char **str) } /* + * Read the next element as binary data. + * 0 is success, < 0 is failure. + */ +static int ebml_read_binary(ByteIOContext *pb, int length, EbmlBin *bin) +{ + av_free(bin->data); + if (!(bin->data = av_malloc(length))) + return AVERROR(ENOMEM); + + bin->size = length; + bin->pos = url_ftell(pb); + if (get_buffer(pb, bin->data, length) != length) + return AVERROR(EIO); + + return 0; +} + +/* * 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. @@ -618,24 +636,6 @@ static int ebml_read_master(MatroskaDemuxContext *matroska, int length) } /* - * Read the next element as binary data. - * 0 is success, < 0 is failure. - */ -static int ebml_read_binary(ByteIOContext *pb, int length, EbmlBin *bin) -{ - av_free(bin->data); - if (!(bin->data = av_malloc(length))) - return AVERROR(ENOMEM); - - bin->size = length; - bin->pos = url_ftell(pb); - if (get_buffer(pb, bin->data, length) != length) - return AVERROR(EIO); - - return 0; -} - -/* * Read signed/unsigned "EBML" numbers. * Return: number of bytes processed, < 0 on error. * XXX: use ebml_read_num(). @@ -696,124 +696,54 @@ static int matroska_ebmlnum_sint(uint8_t *data, uint32_t size, int64_t *num) return res; } +static int ebml_parse_elem(MatroskaDemuxContext *matroska, + EbmlSyntax *syntax, void *data); -static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, - int num) +static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, + uint32_t id, void *data) { - MatroskaTrack *tracks = matroska->tracks.elem; int i; - - for (i=0; i < matroska->tracks.nb_elem; i++) - if (tracks[i].num == num) - return &tracks[i]; - - av_log(matroska->ctx, AV_LOG_ERROR, "Invalid track number %d\n", num); - return NULL; + for (i=0; syntax[i].id; i++) + if (id == syntax[i].id) + break; + if (!syntax[i].id) + av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%X\n", id); + return ebml_parse_elem(matroska, &syntax[i], data); } - -/* - * Put one packet in an application-supplied AVPacket struct. - * Returns 0 on success or -1 on failure. - */ -static int matroska_deliver_packet(MatroskaDemuxContext *matroska, - AVPacket *pkt) +static int ebml_parse(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, + void *data) { - 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; + uint32_t id; + int res = ebml_read_element_id(matroska, &id); + return res < 0 ? res : ebml_parse_id(matroska, syntax, id, data); } -/* - * Put a packet into our internal queue. Will be delivered to the - * user/application during the next get_packet() call. - */ -static void matroska_queue_packet(MatroskaDemuxContext *matroska, AVPacket *pkt) +static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, + void *data) { - matroska->packets = - av_realloc(matroska->packets, (matroska->num_packets + 1) * - sizeof(AVPacket *)); - matroska->packets[matroska->num_packets] = pkt; - matroska->num_packets++; -} + int i, res = 0; -/* - * Free all packets in our internal queue. - */ -static void matroska_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]); + for (i=0; syntax[i].id; i++) + switch (syntax[i].type) { + case EBML_UINT: + *(uint64_t *)((char *)data+syntax[i].data_offset) = syntax[i].def.u; + break; + case EBML_FLOAT: + *(double *)((char *)data+syntax[i].data_offset) = syntax[i].def.f; + break; + case EBML_STR: + case EBML_UTF8: + *(char **)((char *)data+syntax[i].data_offset) = av_strdup(syntax[i].def.s); + break; } - av_free(matroska->packets); - matroska->packets = NULL; - matroska->num_packets = 0; - } -} - - -/* - * Autodetecting... - */ -static int matroska_probe(AVProbeData *p) -{ - uint64_t total = 0; - int len_mask = 0x80, size = 1, n = 1; - char probe_data[] = "matroska"; - - /* 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)-1); n++) - if (!memcmp(p->buf+n, probe_data, sizeof(probe_data)-1)) - return AVPROBE_SCORE_MAX; + while (!res && !ebml_level_end(matroska)) + res = ebml_parse(matroska, syntax, data); - return 0; + return res; } -static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, - uint32_t id, void *data); -static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, - void *data); - static int ebml_parse_elem(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, void *data) { @@ -857,51 +787,6 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska, return res; } -static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, - uint32_t id, void *data) -{ - int i; - for (i=0; syntax[i].id; i++) - if (id == syntax[i].id) - break; - if (!syntax[i].id) - av_log(matroska->ctx, AV_LOG_INFO, "Unknown entry 0x%X\n", id); - return ebml_parse_elem(matroska, &syntax[i], data); -} - -static int ebml_parse(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, - void *data) -{ - uint32_t id; - int res = ebml_read_element_id(matroska, &id); - return res < 0 ? res : ebml_parse_id(matroska, syntax, id, data); -} - -static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, - void *data) -{ - int i, res = 0; - - for (i=0; syntax[i].id; i++) - switch (syntax[i].type) { - case EBML_UINT: - *(uint64_t *)((char *)data+syntax[i].data_offset) = syntax[i].def.u; - break; - case EBML_FLOAT: - *(double *)((char *)data+syntax[i].data_offset) = syntax[i].def.f; - break; - case EBML_STR: - case EBML_UTF8: - *(char **)((char *)data+syntax[i].data_offset) = av_strdup(syntax[i].def.s); - break; - } - - while (!res && !ebml_level_end(matroska)) - res = ebml_parse(matroska, syntax, data); - - return res; -} - static void ebml_free(EbmlSyntax *syntax, void *data) { int i, j; @@ -925,6 +810,61 @@ static void ebml_free(EbmlSyntax *syntax, void *data) } } + +/* + * Autodetecting... + */ +static int matroska_probe(AVProbeData *p) +{ + uint64_t total = 0; + int len_mask = 0x80, size = 1, n = 1; + char probe_data[] = "matroska"; + + /* 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)-1); n++) + if (!memcmp(p->buf+n, probe_data, sizeof(probe_data)-1)) + return AVPROBE_SCORE_MAX; + + return 0; +} + +static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, + int num) +{ + MatroskaTrack *tracks = matroska->tracks.elem; + int i; + + for (i=0; i < matroska->tracks.nb_elem; i++) + if (tracks[i].num == num) + return &tracks[i]; + + av_log(matroska->ctx, AV_LOG_ERROR, "Invalid track number %d\n", num); + return NULL; +} + static int matroska_decode_buffer(uint8_t** buf, int* buf_size, MatroskaTrack *track) { @@ -1378,6 +1318,62 @@ static int matroska_read_header(AVFormatContext *s, AVFormatParameters *ap) return 0; } +/* + * Put a packet into our internal queue. Will be delivered to the + * user/application during the next get_packet() call. + */ +static void matroska_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++; +} + +/* + * Put one packet in an application-supplied AVPacket struct. + * Returns 0 on success or -1 on failure. + */ +static int matroska_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; +} + +/* + * Free all packets in our internal queue. + */ +static void matroska_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; + } +} + static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size, int64_t pos, uint64_t cluster_time, uint64_t duration, int is_keyframe) |