matroskadec: reorder some functions in a more logical order
Originally committed as revision 14604 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
		
							parent
							
								
									1b6d23bbcb
								
							
						
					
					
						commit
						737c40da20
					
				@ -594,6 +594,24 @@ static int ebml_read_ascii(ByteIOContext *pb, int size, char **str)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
@ -617,24 +635,6 @@ static int ebml_read_master(MatroskaDemuxContext *matroska, int length)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
@ -696,166 +696,8 @@ static int matroska_ebmlnum_sint(uint8_t *data, uint32_t size, int64_t *num)
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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 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)
 | 
			
		||||
{
 | 
			
		||||
    ByteIOContext *pb = matroska->ctx->pb;
 | 
			
		||||
    uint32_t id = syntax->id;
 | 
			
		||||
    uint64_t length;
 | 
			
		||||
    int res;
 | 
			
		||||
 | 
			
		||||
    data = (char *)data + syntax->data_offset;
 | 
			
		||||
    if (syntax->list_elem_size) {
 | 
			
		||||
        EbmlList *list = data;
 | 
			
		||||
        list->elem = av_realloc(list->elem, (list->nb_elem+1)*syntax->list_elem_size);
 | 
			
		||||
        data = (char*)list->elem + list->nb_elem*syntax->list_elem_size;
 | 
			
		||||
        memset(data, 0, syntax->list_elem_size);
 | 
			
		||||
        list->nb_elem++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (syntax->type != EBML_PASS && syntax->type != EBML_STOP)
 | 
			
		||||
        if ((res = ebml_read_num(matroska, 8, &length)) < 0)
 | 
			
		||||
            return res;
 | 
			
		||||
 | 
			
		||||
    switch (syntax->type) {
 | 
			
		||||
    case EBML_UINT:  res = ebml_read_uint  (pb, length, data);  break;
 | 
			
		||||
    case EBML_FLOAT: res = ebml_read_float (pb, length, data);  break;
 | 
			
		||||
    case EBML_STR:
 | 
			
		||||
    case EBML_UTF8:  res = ebml_read_ascii (pb, length, data);  break;
 | 
			
		||||
    case EBML_BIN:   res = ebml_read_binary(pb, length, data);  break;
 | 
			
		||||
    case EBML_NEST:  if ((res=ebml_read_master(matroska, length)) < 0)
 | 
			
		||||
                         return res;
 | 
			
		||||
                     if (id == MATROSKA_ID_SEGMENT)
 | 
			
		||||
                         matroska->segment_start = url_ftell(matroska->ctx->pb);
 | 
			
		||||
                     return ebml_parse_nest(matroska, syntax->def.n, data);
 | 
			
		||||
    case EBML_PASS:  return ebml_parse_id(matroska, syntax->def.n, id, data);
 | 
			
		||||
    case EBML_STOP:  *(int *)data = 1;      return 1;
 | 
			
		||||
    default:         url_fskip(pb, length); return 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (res == AVERROR_INVALIDDATA)
 | 
			
		||||
        av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n");
 | 
			
		||||
    else if (res == AVERROR(EIO))
 | 
			
		||||
        av_log(matroska->ctx, AV_LOG_ERROR, "Read error\n");
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
                           EbmlSyntax *syntax, void *data);
 | 
			
		||||
 | 
			
		||||
static int ebml_parse_id(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
 | 
			
		||||
                         uint32_t id, void *data)
 | 
			
		||||
@ -902,6 +744,49 @@ static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ebml_parse_elem(MatroskaDemuxContext *matroska,
 | 
			
		||||
                           EbmlSyntax *syntax, void *data)
 | 
			
		||||
{
 | 
			
		||||
    ByteIOContext *pb = matroska->ctx->pb;
 | 
			
		||||
    uint32_t id = syntax->id;
 | 
			
		||||
    uint64_t length;
 | 
			
		||||
    int res;
 | 
			
		||||
 | 
			
		||||
    data = (char *)data + syntax->data_offset;
 | 
			
		||||
    if (syntax->list_elem_size) {
 | 
			
		||||
        EbmlList *list = data;
 | 
			
		||||
        list->elem = av_realloc(list->elem, (list->nb_elem+1)*syntax->list_elem_size);
 | 
			
		||||
        data = (char*)list->elem + list->nb_elem*syntax->list_elem_size;
 | 
			
		||||
        memset(data, 0, syntax->list_elem_size);
 | 
			
		||||
        list->nb_elem++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (syntax->type != EBML_PASS && syntax->type != EBML_STOP)
 | 
			
		||||
        if ((res = ebml_read_num(matroska, 8, &length)) < 0)
 | 
			
		||||
            return res;
 | 
			
		||||
 | 
			
		||||
    switch (syntax->type) {
 | 
			
		||||
    case EBML_UINT:  res = ebml_read_uint  (pb, length, data);  break;
 | 
			
		||||
    case EBML_FLOAT: res = ebml_read_float (pb, length, data);  break;
 | 
			
		||||
    case EBML_STR:
 | 
			
		||||
    case EBML_UTF8:  res = ebml_read_ascii (pb, length, data);  break;
 | 
			
		||||
    case EBML_BIN:   res = ebml_read_binary(pb, length, data);  break;
 | 
			
		||||
    case EBML_NEST:  if ((res=ebml_read_master(matroska, length)) < 0)
 | 
			
		||||
                         return res;
 | 
			
		||||
                     if (id == MATROSKA_ID_SEGMENT)
 | 
			
		||||
                         matroska->segment_start = url_ftell(matroska->ctx->pb);
 | 
			
		||||
                     return ebml_parse_nest(matroska, syntax->def.n, data);
 | 
			
		||||
    case EBML_PASS:  return ebml_parse_id(matroska, syntax->def.n, id, data);
 | 
			
		||||
    case EBML_STOP:  *(int *)data = 1;      return 1;
 | 
			
		||||
    default:         url_fskip(pb, length); return 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (res == AVERROR_INVALIDDATA)
 | 
			
		||||
        av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n");
 | 
			
		||||
    else if (res == AVERROR(EIO))
 | 
			
		||||
        av_log(matroska->ctx, AV_LOG_ERROR, "Read error\n");
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user