Commit 737c40da authored by Aurelien Jacobs's avatar Aurelien Jacobs

matroskadec: reorder some functions in a more logical order

Originally committed as revision 14604 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 1b6d23bb
......@@ -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,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;
}
/*
* 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++;
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);
}
/*
* Free all packets in our internal queue.
*/
static void matroska_clear_queue(MatroskaDemuxContext *matroska)
static int ebml_parse(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
void *data)
{
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;
}
uint32_t id;
int res = ebml_read_element_id(matroska, &id);
return res < 0 ? res : ebml_parse_id(matroska, syntax, id, data);
}
/*
* Autodetecting...
*/
static int matroska_probe(AVProbeData *p)
static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax,
void *data)
{
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;
int i, res = 0;
/* length of header */
total = p->buf[4];
while (size <= 8 && !(total & len_mask)) {
size++;
len_mask >>= 1;
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;
}
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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment