#include <stdio.h>
#include "avformat.h"
#include "internal.h"
+#include "avio_internal.h"
/* For ff_codec_get_id(). */
#include "riff.h"
#include "isom.h"
int sub_packet_size;
int sub_packet_cnt;
int pkt_cnt;
+ uint64_t buf_timecode;
uint8_t *buf;
} MatroskaTrackAudio;
static EbmlSyntax matroska_blockgroup[] = {
{ MATROSKA_ID_BLOCK, EBML_BIN, 0, offsetof(MatroskaBlock,bin) },
{ MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock,bin) },
- { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock,duration), {.u=AV_NOPTS_VALUE} },
+ { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock,duration) },
{ MATROSKA_ID_BLOCKREFERENCE, EBML_UINT, 0, offsetof(MatroskaBlock,reference) },
{ 1, EBML_UINT, 0, offsetof(MatroskaBlock,non_simple), {.u=1} },
{ 0 }
static int ebml_level_end(MatroskaDemuxContext *matroska)
{
AVIOContext *pb = matroska->ctx->pb;
- int64_t pos = url_ftell(pb);
+ int64_t pos = avio_tell(pb);
if (matroska->num_levels > 0) {
MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];
int read = 1, n = 1;
uint64_t total = 0;
- /* The first byte tells us the length in bytes - get_byte() can normally
+ /* The first byte tells us the length in bytes - avio_r8() can normally
* return 0, but since that's not a valid first ebmlID byte, we can
* use it safely here to catch EOS. */
- if (!(total = get_byte(pb))) {
+ if (!(total = avio_r8(pb))) {
/* we might encounter EOS here */
if (!url_feof(pb)) {
- int64_t pos = url_ftell(pb);
+ int64_t pos = avio_tell(pb);
av_log(matroska->ctx, AV_LOG_ERROR,
"Read error at pos. %"PRIu64" (0x%"PRIx64")\n",
pos, pos);
/* get the length of the EBML number */
read = 8 - ff_log2_tab[total];
if (read > max_size) {
- int64_t pos = url_ftell(pb) - 1;
+ int64_t pos = avio_tell(pb) - 1;
av_log(matroska->ctx, AV_LOG_ERROR,
"Invalid EBML number size tag 0x%02x at pos %"PRIu64" (0x%"PRIx64")\n",
(uint8_t) total, pos, pos);
/* read out length */
total ^= 1 << ff_log2_tab[total];
while (n++ < read)
- total = (total << 8) | get_byte(pb);
+ total = (total << 8) | avio_r8(pb);
*number = total;
/* big-endian ordering; build up number */
*num = 0;
while (n++ < size)
- *num = (*num << 8) | get_byte(pb);
+ *num = (*num << 8) | avio_r8(pb);
return 0;
}
if (size == 0) {
*num = 0;
} else if (size == 4) {
- *num= av_int2flt(get_be32(pb));
+ *num= av_int2flt(avio_rb32(pb));
} else if(size==8){
- *num= av_int2dbl(get_be64(pb));
+ *num= av_int2dbl(avio_rb64(pb));
} else
return AVERROR_INVALIDDATA;
* byte more, read the string and NULL-terminate it ourselves. */
if (!(*str = av_malloc(size + 1)))
return AVERROR(ENOMEM);
- if (get_buffer(pb, (uint8_t *) *str, size) != size) {
+ if (avio_read(pb, (uint8_t *) *str, size) != size) {
av_freep(str);
return AVERROR(EIO);
}
return AVERROR(ENOMEM);
bin->size = length;
- bin->pos = url_ftell(pb);
- if (get_buffer(pb, bin->data, length) != length) {
+ bin->pos = avio_tell(pb);
+ if (avio_read(pb, bin->data, length) != length) {
av_freep(&bin->data);
return AVERROR(EIO);
}
}
level = &matroska->levels[matroska->num_levels++];
- level->start = url_ftell(pb);
+ level->start = avio_tell(pb);
level->length = length;
return 0;
uint8_t *data, uint32_t size, uint64_t *num)
{
AVIOContext pb;
- init_put_byte(&pb, data, size, 0, NULL, NULL, NULL, NULL);
+ ffio_init_context(&pb, data, size, 0, NULL, NULL, NULL, NULL);
return ebml_read_num(matroska, &pb, FFMIN(size, 8), num);
}
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);
+ matroska->segment_start = avio_tell(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: return 1;
- default: return url_fseek(pb,length,SEEK_CUR)<0 ? AVERROR(EIO) : 0;
+ default: return avio_skip(pb,length)<0 ? AVERROR(EIO) : 0;
}
if (res == AVERROR_INVALIDDATA)
av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n");
if (tags[i].target.attachuid) {
MatroskaAttachement *attachment = matroska->attachments.elem;
for (j=0; j<matroska->attachments.nb_elem; j++)
- if (attachment[j].uid == tags[i].target.attachuid)
+ if (attachment[j].uid == tags[i].target.attachuid
+ && attachment[j].stream)
matroska_convert_tag(s, &tags[i].tag,
&attachment[j].stream->metadata, NULL);
} else if (tags[i].target.chapteruid) {
MatroskaChapter *chapter = matroska->chapters.elem;
for (j=0; j<matroska->chapters.nb_elem; j++)
- if (chapter[j].uid == tags[i].target.chapteruid)
+ if (chapter[j].uid == tags[i].target.chapteruid
+ && chapter[j].chapter)
matroska_convert_tag(s, &tags[i].tag,
&chapter[j].chapter->metadata, NULL);
} else if (tags[i].target.trackuid) {
MatroskaTrack *track = matroska->tracks.elem;
for (j=0; j<matroska->tracks.nb_elem; j++)
- if (track[j].uid == tags[i].target.trackuid)
+ if (track[j].uid == tags[i].target.trackuid && track[j].stream)
matroska_convert_tag(s, &tags[i].tag,
&track[j].stream->metadata, NULL);
} else {
EbmlList *seekhead_list = &matroska->seekhead;
MatroskaSeekhead *seekhead = seekhead_list->elem;
uint32_t level_up = matroska->level_up;
- int64_t before_pos = url_ftell(matroska->ctx->pb);
+ int64_t before_pos = avio_tell(matroska->ctx->pb);
uint32_t saved_id = matroska->current_id;
MatroskaLevel level;
int i;
// we should not do any seeking in the streaming case
- if (url_is_streamed(matroska->ctx->pb) ||
+ if (!matroska->ctx->pb->seekable ||
(matroska->ctx->flags & AVFMT_FLAG_IGNIDX))
return;
continue;
/* seek */
- if (url_fseek(matroska->ctx->pb, offset, SEEK_SET) != offset)
+ if (avio_seek(matroska->ctx->pb, offset, SEEK_SET) != offset)
continue;
/* We don't want to lose our seekhead level, so we add
}
/* seek back */
- url_fseek(matroska->ctx->pb, before_pos, SEEK_SET);
+ avio_seek(matroska->ctx->pb, before_pos, SEEK_SET);
matroska->level_up = level_up;
matroska->current_id = saved_id;
}
} else if (!strcmp(track->codec_id, "A_MS/ACM")
&& track->codec_priv.size >= 14
&& track->codec_priv.data != NULL) {
- init_put_byte(&b, track->codec_priv.data, track->codec_priv.size,
- URL_RDONLY, NULL, NULL, NULL, NULL);
+ ffio_init_context(&b, track->codec_priv.data, track->codec_priv.size,
+ AVIO_RDONLY, NULL, NULL, NULL, NULL);
ff_get_wav_header(&b, st->codec, track->codec_priv.size);
codec_id = st->codec->codec_id;
extradata_offset = FFMIN(track->codec_priv.size, 18);
extradata = av_mallocz(extradata_size);
if (extradata == NULL)
return AVERROR(ENOMEM);
- init_put_byte(&b, extradata, extradata_size, 1,
+ ffio_init_context(&b, extradata, extradata_size, 1,
NULL, NULL, NULL, NULL);
- put_buffer(&b, "TTA1", 4);
- put_le16(&b, 1);
- put_le16(&b, track->audio.channels);
- put_le16(&b, track->audio.bitdepth);
- put_le32(&b, track->audio.out_samplerate);
- put_le32(&b, matroska->ctx->duration * track->audio.out_samplerate);
+ avio_write(&b, "TTA1", 4);
+ avio_wl16(&b, 1);
+ avio_wl16(&b, track->audio.channels);
+ avio_wl16(&b, track->audio.bitdepth);
+ avio_wl32(&b, track->audio.out_samplerate);
+ avio_wl32(&b, matroska->ctx->duration * track->audio.out_samplerate);
} else if (codec_id == CODEC_ID_RV10 || codec_id == CODEC_ID_RV20 ||
codec_id == CODEC_ID_RV30 || codec_id == CODEC_ID_RV40) {
extradata_offset = 26;
} else if (codec_id == CODEC_ID_RA_288 || codec_id == CODEC_ID_COOK ||
codec_id == CODEC_ID_ATRAC3 || codec_id == CODEC_ID_SIPR) {
int flavor;
- init_put_byte(&b, track->codec_priv.data,track->codec_priv.size,
+ ffio_init_context(&b, track->codec_priv.data,track->codec_priv.size,
0, NULL, NULL, NULL, NULL);
- url_fskip(&b, 22);
- flavor = get_be16(&b);
- track->audio.coded_framesize = get_be32(&b);
- url_fskip(&b, 12);
- track->audio.sub_packet_h = get_be16(&b);
- track->audio.frame_size = get_be16(&b);
- track->audio.sub_packet_size = get_be16(&b);
+ avio_skip(&b, 22);
+ flavor = avio_rb16(&b);
+ track->audio.coded_framesize = avio_rb32(&b);
+ avio_skip(&b, 12);
+ track->audio.sub_packet_h = avio_rb16(&b);
+ track->audio.frame_size = avio_rb16(&b);
+ track->audio.sub_packet_size = avio_rb16(&b);
track->audio.buf = av_malloc(track->audio.frame_size * track->audio.sub_packet_h);
if (codec_id == CODEC_ID_RA_288) {
st->codec->block_align = track->audio.coded_framesize;
st = track->stream;
if (st->discard >= AVDISCARD_ALL)
return res;
- if (duration == AV_NOPTS_VALUE)
+ if (!duration)
duration = track->default_duration / matroska->time_scale;
block_time = AV_RB16(data);
int x;
if (!track->audio.pkt_cnt) {
+ if (track->audio.sub_packet_cnt == 0)
+ track->audio.buf_timecode = timecode;
if (st->codec->codec_id == CODEC_ID_RA_288)
for (x=0; x<h/2; x++)
memcpy(track->audio.buf+x*2*w+y*cfs,
av_new_packet(pkt, a);
memcpy(pkt->data, track->audio.buf
+ a * (h*w / a - track->audio.pkt_cnt--), a);
+ pkt->pts = track->audio.buf_timecode;
+ track->audio.buf_timecode = AV_NOPTS_VALUE;
pkt->pos = pos;
pkt->stream_index = st->index;
dynarray_add(&matroska->packets,&matroska->num_packets,pkt);
EbmlList *blocks_list;
MatroskaBlock *blocks;
int i, res;
- int64_t pos = url_ftell(matroska->ctx->pb);
+ int64_t pos = avio_tell(matroska->ctx->pb);
matroska->prev_pkt = NULL;
if (matroska->current_id)
pos -= 4; /* sizeof the ID which was already read */
timestamp = FFMAX(timestamp, st->index_entries[0].timestamp);
if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
- url_fseek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET);
+ avio_seek(s->pb, st->index_entries[st->nb_index_entries-1].pos, SEEK_SET);
while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0) {
matroska_clear_queue(matroska);
if (matroska_parse_cluster(matroska) < 0)
index_min = index;
for (i=0; i < matroska->tracks.nb_elem; i++) {
+ tracks[i].audio.pkt_cnt = 0;
+ tracks[i].audio.sub_packet_cnt = 0;
+ tracks[i].audio.buf_timecode = AV_NOPTS_VALUE;
tracks[i].end_timecode = 0;
if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE
&& !tracks[i].stream->discard != AVDISCARD_ALL) {
}
}
- url_fseek(s->pb, st->index_entries[index_min].pos, SEEK_SET);
+ avio_seek(s->pb, st->index_entries[index_min].pos, SEEK_SET);
matroska->skip_to_keyframe = !(flags & AVSEEK_FLAG_ANY);
matroska->skip_to_timecode = st->index_entries[index].timestamp;
matroska->done = 0;