Commit 8978feda authored by Anton Khirnov's avatar Anton Khirnov
Browse files

avio: introduce an AVIOContext.seekable field

Use it instead of url_is_streamed and AVIOContext.is_streamed.
parent 79997def
......@@ -2260,7 +2260,7 @@ static int http_prepare_data(HTTPContext *c)
/* XXX: potential leak */
return -1;
}
c->fmt_ctx.pb->is_streamed = 1;
c->fmt_ctx.pb->seekable = 0;
/*
* HACK to avoid mpeg ps muxer to spit many underflow errors
......@@ -2399,7 +2399,7 @@ static int http_prepare_data(HTTPContext *c)
}
ost = ctx->streams[pkt.stream_index];
ctx->pb->is_streamed = 1;
ctx->pb->seekable = 0;
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
if (pkt.pts != AV_NOPTS_VALUE)
......@@ -2436,7 +2436,7 @@ static int http_prepare_data(HTTPContext *c)
/* XXX: potential leak */
return -1;
}
c->fmt_ctx.pb->is_streamed = 1;
c->fmt_ctx.pb->seekable = 0;
av_write_trailer(ctx);
len = url_close_dyn_buf(ctx->pb, &c->pb_buffer);
c->buffer_ptr = c->pb_buffer;
......@@ -2723,7 +2723,7 @@ static int http_receive_data(HTTPContext *c)
pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
0, NULL, NULL, NULL, NULL);
pb->is_streamed = 1;
pb->seekable = 0;
if (av_open_input_stream(&s, pb, c->stream->feed_filename, fmt_in, NULL) < 0) {
av_free(pb);
......
......@@ -238,7 +238,7 @@ static int aiff_read_header(AVFormatContext *s,
offset += avio_tell(pb); /* Compute absolute data offset */
if (st->codec->block_align) /* Assume COMM already parsed */
goto got_sound;
if (url_is_streamed(pb)) {
if (!pb->seekable) {
av_log(s, AV_LOG_ERROR, "file is not seekable\n");
return -1;
}
......
......@@ -124,7 +124,7 @@ static int aiff_write_trailer(AVFormatContext *s)
end_size++;
}
if (!url_is_streamed(s->pb)) {
if (s->pb->seekable) {
/* File length */
avio_seek(pb, aiff->form, SEEK_SET);
avio_wb32(pb, file_size - aiff->form - 4);
......
......@@ -296,7 +296,7 @@ static int ape_read_header(AVFormatContext * s, AVFormatParameters * ap)
ape_dumpinfo(s, ape);
/* try to read APE tags */
if (!url_is_streamed(pb)) {
if (pb->seekable) {
ff_ape_parse_tag(s);
avio_seek(pb, 0, SEEK_SET);
}
......
......@@ -347,7 +347,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data
avio_wl64(pb, duration); /* end time stamp (in 100ns units) */
avio_wl64(pb, asf->duration); /* duration (in 100ns units) */
avio_wl64(pb, PREROLL_TIME); /* start time stamp */
avio_wl32(pb, (asf->is_streamed || url_is_streamed(pb)) ? 3 : 2); /* ??? */
avio_wl32(pb, (asf->is_streamed || !pb->seekable ) ? 3 : 2); /* ??? */
avio_wl32(pb, s->packet_size); /* packet size */
avio_wl32(pb, s->packet_size); /* packet size */
avio_wl32(pb, bit_rate); /* Nominal data rate in bps */
......@@ -866,7 +866,7 @@ static int asf_write_trailer(AVFormatContext *s)
}
avio_flush(s->pb);
if (asf->is_streamed || url_is_streamed(s->pb)) {
if (asf->is_streamed || !s->pb->seekable) {
put_chunk(s, 0x4524, 0, 0); /* end of stream */
} else {
/* rewrite an updated header */
......
......@@ -91,7 +91,7 @@ static int au_write_trailer(AVFormatContext *s)
AVIOContext *pb = s->pb;
int64_t file_size;
if (!url_is_streamed(s->pb)) {
if (s->pb->seekable) {
/* update file size */
file_size = avio_tell(pb);
......
......@@ -665,7 +665,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
break;
case MKTAG('i', 'n', 'd', 'x'):
i= avio_tell(pb);
if(!url_is_streamed(pb) && !(s->flags & AVFMT_FLAG_IGNIDX)){
if(pb->seekable && !(s->flags & AVFMT_FLAG_IGNIDX)){
read_braindead_odml_indx(s, 0);
}
avio_seek(pb, i+size, SEEK_SET);
......@@ -721,7 +721,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
return -1;
}
if(!avi->index_loaded && !url_is_streamed(pb))
if(!avi->index_loaded && pb->seekable)
avi_load_index(s);
avi->index_loaded = 1;
avi->non_interleaved |= guess_ni_flag(s);
......
......@@ -197,7 +197,7 @@ static int avi_write_header(AVFormatContext *s)
}
avio_wl32(pb, bitrate / 8); /* XXX: not quite exact */
avio_wl32(pb, 0); /* padding */
if (url_is_streamed(pb))
if (!pb->seekable)
avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */
else
avio_wl32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */
......@@ -259,7 +259,7 @@ static int avi_write_header(AVFormatContext *s)
avio_wl32(pb, 0); /* start */
avist->frames_hdr_strm = avio_tell(pb); /* remember this offset to fill later */
if (url_is_streamed(pb))
if (!pb->seekable)
avio_wl32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */
else
avio_wl32(pb, 0); /* length, XXX: filled later */
......@@ -303,7 +303,7 @@ static int avi_write_header(AVFormatContext *s)
}
}
if (!url_is_streamed(pb)) {
if (pb->seekable) {
unsigned char tag[5];
int j;
......@@ -362,7 +362,7 @@ static int avi_write_header(AVFormatContext *s)
ff_end_tag(pb, list2);
}
if (!url_is_streamed(pb)) {
if (pb->seekable) {
/* AVI could become an OpenDML one, if it grows beyond 2Gb range */
avi->odml_list = ff_start_tag(pb, "JUNK");
ffio_wfourcc(pb, "odml");
......@@ -406,7 +406,7 @@ static int avi_write_ix(AVFormatContext *s)
char ix_tag[] = "ix00";
int i, j;
assert(!url_is_streamed(pb));
assert(pb->seekable);
if (avi->riff_id > AVI_MASTER_INDEX_SIZE)
return -1;
......@@ -464,7 +464,7 @@ static int avi_write_idx1(AVFormatContext *s)
int i;
char tag[5];
if (!url_is_streamed(pb)) {
if (pb->seekable) {
AVIStream *avist;
AVIIentry* ie = 0, *tie;
int empty, stream_id = -1;
......@@ -532,7 +532,7 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
avist->packet_count++;
// Make sure to put an OpenDML chunk when the file size exceeds the limits
if (!url_is_streamed(pb) &&
if (pb->seekable &&
(avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) {
avi_write_ix(s);
......@@ -552,7 +552,7 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
avist->audio_strm_length += size;
}
if (!url_is_streamed(s->pb)) {
if (s->pb->seekable) {
AVIIndex* idx = &avist->indexes;
int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE;
int id = idx->entry % AVI_INDEX_CLUSTER_SIZE;
......@@ -590,7 +590,7 @@ static int avi_write_trailer(AVFormatContext *s)
int i, j, n, nb_frames;
int64_t file_size;
if (!url_is_streamed(pb)){
if (pb->seekable){
if (avi->riff_id == 1) {
ff_end_tag(pb, avi->movi_list);
res = avi_write_idx1(s);
......
......@@ -332,6 +332,8 @@ attribute_deprecated int av_register_protocol(URLProtocol *protocol);
*/
int av_register_protocol2(URLProtocol *protocol, int size);
#define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */
/**
* Bytestream IO Context.
* New fields can be added to the end with minor version bumps.
......@@ -351,7 +353,9 @@ typedef struct {
int must_flush; /**< true if the next seek should flush */
int eof_reached; /**< true if eof reached */
int write_flag; /**< true if open for writing */
int is_streamed;
#if FF_API_OLD_AVIO
attribute_deprecated int is_streamed;
#endif
int max_packet_size;
unsigned long checksum;
unsigned char *checksum_ptr;
......@@ -360,6 +364,10 @@ typedef struct {
int (*read_pause)(void *opaque, int pause);
int64_t (*read_seek)(void *opaque, int stream_index,
int64_t timestamp, int flags);
/**
* A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
*/
int seekable;
} AVIOContext;
#if FF_API_OLD_AVIO
......@@ -604,10 +612,15 @@ unsigned int avio_rb24(AVIOContext *s);
unsigned int avio_rb32(AVIOContext *s);
uint64_t avio_rb64(AVIOContext *s);
static inline int url_is_streamed(AVIOContext *s)
#if FF_API_OLD_AVIO
/**
* @deprecated Use AVIOContext.seekable field directly.
*/
attribute_deprecated static inline int url_is_streamed(AVIOContext *s)
{
return s->is_streamed;
return !s->seekable;
}
#endif
/**
* Create and initialize a AVIOContext for accessing the
......
......@@ -62,7 +62,10 @@ int ffio_init_context(AVIOContext *s,
s->must_flush = 0;
s->eof_reached = 0;
s->error = 0;
#if FF_API_OLD_AVIO
s->is_streamed = 0;
#endif
s->seekable = AVIO_SEEKABLE_NORMAL;
s->max_packet_size = 0;
s->update_checksum= NULL;
if(!read_packet && !write_flag){
......@@ -202,7 +205,7 @@ int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
offset1 >= 0 && offset1 <= (s->buf_end - s->buffer)) {
/* can do the seek inside the buffer */
s->buf_ptr = s->buffer + offset1;
} else if ((s->is_streamed ||
} else if ((!s->seekable ||
offset1 <= s->buf_end + SHORT_SEEK_THRESHOLD - s->buffer) &&
!s->write_flag && offset1 >= 0 &&
(whence != SEEK_END || force)) {
......@@ -831,7 +834,10 @@ int url_fdopen(AVIOContext **s, URLContext *h)
av_freep(s);
return AVERROR(EIO);
}
#if FF_API_OLD_AVIO
(*s)->is_streamed = h->is_streamed;
#endif
(*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
(*s)->max_packet_size = max_packet_size;
if(h->prot) {
(*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause;
......
......@@ -247,7 +247,7 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, in
BinkDemuxContext *bink = s->priv_data;
AVStream *vst = s->streams[0];
if (url_is_streamed(s->pb))
if (!s->pb->seekable)
return -1;
/* seek to the first frame */
......
......@@ -223,7 +223,7 @@ static int read_header(AVFormatContext *s,
/* stop at data chunk if seeking is not supported or
data chunk size is unknown */
if (found_data && (caf->data_size < 0 || url_is_streamed(pb)))
if (found_data && (caf->data_size < 0 || !pb->seekable))
break;
tag = avio_rb32(pb);
......@@ -236,7 +236,7 @@ static int read_header(AVFormatContext *s,
avio_skip(pb, 4); /* edit count */
caf->data_start = avio_tell(pb);
caf->data_size = size < 0 ? -1 : size - 4;
if (caf->data_size > 0 && !url_is_streamed(pb))
if (caf->data_size > 0 && pb->seekable)
avio_skip(pb, caf->data_size);
found_data = 1;
break;
......
......@@ -281,7 +281,7 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap)
goto fail;
ffm->write_index = avio_rb64(pb);
/* get also filesize */
if (!url_is_streamed(pb)) {
if (pb->seekable) {
ffm->file_size = avio_size(pb);
if (ffm->write_index)
adjust_write_index(s);
......
......@@ -40,7 +40,7 @@ static int read_header(AVFormatContext *s,
AVIOContext *pb = s->pb;
AVStream *st;
if (url_is_streamed(s->pb))
if (!s->pb->seekable)
return AVERROR(EIO);
avio_seek(pb, avio_size(pb) - 36, SEEK_SET);
......
......@@ -98,7 +98,7 @@ static int flac_write_trailer(struct AVFormatContext *s)
if (!ff_flac_is_extradata_valid(s->streams[0]->codec, &format, &streaminfo))
return -1;
if (!url_is_streamed(pb)) {
if (pb->seekable) {
/* rewrite the STREAMINFO header block data */
file_size = avio_tell(pb);
avio_seek(pb, 8, SEEK_SET);
......
......@@ -437,7 +437,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
}
// if not streamed and no duration from metadata then seek to end to find the duration from the timestamps
if(!url_is_streamed(s->pb) && (!s->duration || s->duration==AV_NOPTS_VALUE)){
if(s->pb->seekable && (!s->duration || s->duration==AV_NOPTS_VALUE)){
int size;
const int64_t pos= avio_tell(s->pb);
const int64_t fsize= avio_size(s->pb);
......@@ -539,7 +539,7 @@ static int flv_read_seek2(AVFormatContext *s, int stream_index,
if (ts - min_ts > (uint64_t)(max_ts - ts)) flags |= AVSEEK_FLAG_BACKWARD;
if (url_is_streamed(s->pb)) {
if (!s->pb->seekable) {
if (stream_index < 0) {
stream_index = av_find_default_stream_index(s);
if (stream_index < 0)
......
......@@ -634,7 +634,7 @@ static int gxf_write_header(AVFormatContext *s)
uint8_t tracks[255] = {0};
int i, media_info = 0;
if (url_is_streamed(pb)) {
if (!pb->seekable) {
av_log(s, AV_LOG_ERROR, "gxf muxer does not support streamed output, patch welcome");
return -1;
}
......
......@@ -229,7 +229,7 @@ void ff_id3v1_read(AVFormatContext *s)
uint8_t buf[ID3v1_TAG_SIZE];
int64_t filesize, position = avio_tell(s->pb);
if (!url_is_streamed(s->pb)) {
if (s->pb->seekable) {
/* XXX: change that */
filesize = avio_size(s->pb);
if (filesize > 128) {
......
......@@ -1117,7 +1117,7 @@ static void matroska_execute_seekhead(MatroskaDemuxContext *matroska)
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;
......
......@@ -848,7 +848,7 @@ static int mkv_write_header(AVFormatContext *s)
if (ret < 0) return ret;
}
if (url_is_streamed(s->pb))
if (!s->pb->seekable)
mkv_write_seekhead(pb, mkv->main_seekhead);
mkv->cues = mkv_start_cues(mkv->segment_offset);
......@@ -1024,7 +1024,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
return AVERROR(EINVAL);
}
if (url_is_streamed(s->pb)) {
if (!s->pb->seekable) {
if (!mkv->dyn_bc)
url_open_dyn_buf(&mkv->dyn_bc);
pb = mkv->dyn_bc;
......@@ -1076,16 +1076,16 @@ static int mkv_copy_packet(MatroskaMuxContext *mkv, const AVPacket *pkt)
static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
{
MatroskaMuxContext *mkv = s->priv_data;
AVIOContext *pb = url_is_streamed(s->pb) ? mkv->dyn_bc : s->pb;
AVIOContext *pb = s->pb->seekable ? s->pb : mkv->dyn_bc;
AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
int ret, keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY);
int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
int cluster_size = avio_tell(pb) - (url_is_streamed(s->pb) ? 0 : mkv->cluster_pos);
int cluster_size = avio_tell(pb) - (s->pb->seekable ? mkv->cluster_pos : 0);
// start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or
// after 4k and on a keyframe
if (mkv->cluster_pos &&
((url_is_streamed(s->pb) && (cluster_size > 32*1024 || ts > mkv->cluster_pts + 1000))
((!s->pb->seekable && (cluster_size > 32*1024 || ts > mkv->cluster_pts + 1000))
|| cluster_size > 5*1024*1024 || ts > mkv->cluster_pts + 5000
|| (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe && cluster_size > 4*1024))) {
av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
......@@ -1139,7 +1139,7 @@ static int mkv_write_trailer(AVFormatContext *s)
end_ebml_master(pb, mkv->cluster);
}
if (!url_is_streamed(pb)) {
if (pb->seekable) {
cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES , cuespos);
......
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