summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-10-29 14:20:56 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-10-29 14:20:56 +0000
commitda24c5e330ab90b5249f4fb94044b78919f64d4f (patch)
tree00bfea3d2edb36fba0923df778eac27d409e3aed /libavformat
parentb45a7a18d32e530d784bf2ac0831e27490c3befd (diff)
make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()
Originally committed as revision 2447 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/avformat.h23
-rw-r--r--libavformat/mpeg.c3
-rw-r--r--libavformat/utils.c165
3 files changed, 112 insertions, 79 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 7de9c8ee3c..f3a89fdf4b 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -5,7 +5,7 @@
extern "C" {
#endif
-#define LIBAVFORMAT_BUILD 4608
+#define LIBAVFORMAT_BUILD 4609
#define LIBAVFORMAT_VERSION_INT FFMPEG_VERSION_INT
#define LIBAVFORMAT_VERSION FFMPEG_VERSION
@@ -42,6 +42,7 @@ typedef struct AVPacket {
} AVPacket;
#define PKT_FLAG_KEY 0x0001
+/* initialize optional fields of a packet */
static inline void av_init_packet(AVPacket *pkt)
{
pkt->pts = AV_NOPTS_VALUE;
@@ -102,12 +103,14 @@ typedef struct AVFormatParameters {
int channel; /* used to select dv channel */
const char *device; /* video4linux, audio or DV device */
const char *standard; /* tv standard, NTSC, PAL, SECAM */
+ int mpeg2ts_raw:1; /* force raw MPEG2 transport stream output, if possible */
+ int mpeg2ts_compute_pcr:1; /* compute exact PCR for each transport
+ stream packet (only meaningful if
+ mpeg2ts_raw is TRUE */
} AVFormatParameters;
#define AVFMT_NOFILE 0x0001 /* no file should be opened */
#define AVFMT_NEEDNUMBER 0x0002 /* needs '%d' in filename */
-#define AVFMT_NOHEADER 0x0004 /* signal that no header is present
- (streams are added dynamically) */
#define AVFMT_SHOW_IDS 0x0008 /* show format stream IDs numbers */
#define AVFMT_RAWPICTURE 0x0020 /* format wants AVPicture structure for
raw picture data */
@@ -150,7 +153,7 @@ typedef struct AVInputFormat {
AVFormatParameters *ap);
/* read one packet and put it in 'pkt'. pts and flags are also
set. 'av_new_stream' can be called only if the flag
- AVFMT_NOHEADER is used. */
+ AVFMTCTX_NOHEADER is used. */
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
/* close the stream. The AVFormatContext and AVStreams are not
freed by this function */
@@ -158,7 +161,7 @@ typedef struct AVInputFormat {
/* seek at or before a given pts (given in microsecond). The pts
origin is defined by the stream */
int (*read_seek)(struct AVFormatContext *, int64_t pts);
- /* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_NOHEADER */
+ /* can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER */
int flags;
/* if extensions are defined, then no probe is done. You should
usually not use extension format guessing because it is not
@@ -181,7 +184,7 @@ typedef struct AVStream {
int codec_info_state;
int codec_info_nb_repeat_frames;
int codec_info_nb_real_frames;
- /* PTS generation when outputing stream */
+ /* encoding: PTS generation when outputing stream */
AVFrac pts;
/* ffmpeg.c private use */
int stream_copy; /* if TRUE, just copy stream */
@@ -196,6 +199,9 @@ typedef struct AVStream {
int64_t duration;
} AVStream;
+#define AVFMTCTX_NOHEADER 0x0001 /* signal that no header is present
+ (streams are added dynamically) */
+
#define MAX_STREAMS 20
/* format I/O context */
@@ -218,7 +224,7 @@ typedef struct AVFormatContext {
int track; /* track number, 0 if none */
char genre[32]; /* ID3 genre */
- int flags; /* format specific flags */
+ int ctx_flags; /* format specific flags, see AVFMTCTX_xx */
/* private data for pts handling (do not modify directly) */
int pts_wrap_bits; /* number of bits in pts (used for wrapping control) */
int pts_num, pts_den; /* value to convert to seconds */
@@ -448,6 +454,9 @@ void fifo_write(FifoBuffer *f, uint8_t *buf, int size, uint8_t **wptr_ptr);
/* media file input */
AVInputFormat *av_find_input_format(const char *short_name);
AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened);
+int av_open_input_stream(AVFormatContext **ic_ptr,
+ ByteIOContext *pb, const char *filename,
+ AVInputFormat *fmt, AVFormatParameters *ap);
int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
AVInputFormat *fmt,
int buf_size,
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index 45ffdf6841..9c138556f1 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -479,6 +479,8 @@ static int mpegps_read_header(AVFormatContext *s,
{
MpegDemuxContext *m = s->priv_data;
m->header_state = 0xff;
+ s->ctx_flags |= AVFMTCTX_NOHEADER;
+
/* no need to do more */
return 0;
}
@@ -705,7 +707,6 @@ AVInputFormat mpegps_demux = {
mpegps_read_header,
mpegps_read_packet,
mpegps_read_close,
- .flags = AVFMT_NOHEADER,
};
int mpegps_init(void)
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 70c9e6e192..ddd26f1b7d 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -274,6 +274,56 @@ AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)
/************************************************************/
/* input media file */
+/**
+ * open a media file from an IO stream. 'fmt' must be specified.
+ */
+int av_open_input_stream(AVFormatContext **ic_ptr,
+ ByteIOContext *pb, const char *filename,
+ AVInputFormat *fmt, AVFormatParameters *ap)
+{
+ int err;
+ AVFormatContext *ic;
+
+ ic = av_mallocz(sizeof(AVFormatContext));
+ if (!ic) {
+ err = AVERROR_NOMEM;
+ goto fail;
+ }
+ ic->iformat = fmt;
+ if (pb)
+ ic->pb = *pb;
+ ic->duration = AV_NOPTS_VALUE;
+ ic->start_time = AV_NOPTS_VALUE;
+ pstrcpy(ic->filename, sizeof(ic->filename), filename);
+
+ /* allocate private data */
+ if (fmt->priv_data_size > 0) {
+ ic->priv_data = av_mallocz(fmt->priv_data_size);
+ if (!ic->priv_data) {
+ err = AVERROR_NOMEM;
+ goto fail;
+ }
+ } else {
+ ic->priv_data = NULL;
+ }
+
+ /* default pts settings is MPEG like */
+ av_set_pts_info(ic, 33, 1, 90000);
+
+ err = ic->iformat->read_header(ic, ap);
+ if (err < 0)
+ goto fail;
+ *ic_ptr = ic;
+ return 0;
+ fail:
+ if (ic) {
+ av_freep(&ic->priv_data);
+ }
+ av_free(ic);
+ *ic_ptr = NULL;
+ return err;
+}
+
#define PROBE_BUF_SIZE 2048
/**
@@ -292,20 +342,15 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
int buf_size,
AVFormatParameters *ap)
{
- AVFormatContext *ic = NULL;
- int err, must_open_file;
- unsigned char buf[PROBE_BUF_SIZE];
+ int err, must_open_file, file_opened;
+ uint8_t buf[PROBE_BUF_SIZE];
AVProbeData probe_data, *pd = &probe_data;
-
- ic = av_mallocz(sizeof(AVFormatContext));
- if (!ic) {
- err = AVERROR_NOMEM;
- goto fail;
- }
- ic->duration = AV_NOPTS_VALUE;
- ic->start_time = AV_NOPTS_VALUE;
- pstrcpy(ic->filename, sizeof(ic->filename), filename);
- pd->filename = ic->filename;
+ ByteIOContext pb1, *pb = &pb1;
+
+ file_opened = 0;
+ pd->filename = "";
+ if (filename)
+ pd->filename = filename;
pd->buf = buf;
pd->buf_size = 0;
@@ -317,27 +362,24 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
/* do not open file if the format does not need it. XXX: specific
hack needed to handle RTSP/TCP */
must_open_file = 1;
- if ((fmt && (fmt->flags & AVFMT_NOFILE))
-#ifdef CONFIG_NETWORK
- || (fmt == &rtp_demux && !strcmp(filename, "null"))
-#endif
- ) {
+ if (fmt && (fmt->flags & AVFMT_NOFILE)) {
must_open_file = 0;
}
if (!fmt || must_open_file) {
/* if no file needed do not try to open one */
- if (url_fopen(&ic->pb, filename, URL_RDONLY) < 0) {
+ if (url_fopen(pb, filename, URL_RDONLY) < 0) {
err = AVERROR_IO;
goto fail;
}
+ file_opened = 1;
if (buf_size > 0) {
- url_setbufsize(&ic->pb, buf_size);
+ url_setbufsize(pb, buf_size);
}
if (!fmt) {
/* read probe data */
- pd->buf_size = get_buffer(&ic->pb, buf, PROBE_BUF_SIZE);
- url_fseek(&ic->pb, 0, SEEK_SET);
+ pd->buf_size = get_buffer(pb, buf, PROBE_BUF_SIZE);
+ url_fseek(pb, 0, SEEK_SET);
}
}
@@ -349,65 +391,46 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
/* if still no format found, error */
if (!fmt) {
err = AVERROR_NOFMT;
- goto fail1;
+ goto fail;
}
/* XXX: suppress this hack for redirectors */
#ifdef CONFIG_NETWORK
if (fmt == &redir_demux) {
- err = redir_open(ic_ptr, &ic->pb);
- url_fclose(&ic->pb);
- av_free(ic);
+ err = redir_open(ic_ptr, pb);
+ url_fclose(pb);
return err;
}
#endif
- ic->iformat = fmt;
-
/* check filename in case of an image number is expected */
- if (ic->iformat->flags & AVFMT_NEEDNUMBER) {
- if (filename_number_test(ic->filename) < 0) {
+ if (fmt->flags & AVFMT_NEEDNUMBER) {
+ if (filename_number_test(filename) < 0) {
err = AVERROR_NUMEXPECTED;
- goto fail1;
+ goto fail;
}
}
-
- /* allocate private data */
- if (fmt->priv_data_size > 0) {
- ic->priv_data = av_mallocz(fmt->priv_data_size);
- if (!ic->priv_data) {
- err = AVERROR_NOMEM;
- goto fail1;
- }
- } else
- ic->priv_data = NULL;
-
- /* default pts settings is MPEG like */
- av_set_pts_info(ic, 33, 1, 90000);
-
- err = ic->iformat->read_header(ic, ap);
- if (err < 0)
- goto fail1;
- *ic_ptr = ic;
+ err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);
+ if (err)
+ goto fail;
return 0;
- fail1:
- if (!fmt || must_open_file) {
- url_fclose(&ic->pb);
- }
fail:
- if (ic) {
- av_freep(&ic->priv_data);
- }
- av_free(ic);
+ if (file_opened)
+ url_fclose(pb);
*ic_ptr = NULL;
return err;
+
}
+/*******************************************************/
+
/**
- * Read a packet from a media file
+ * Read a packet from a media file. Use it only for low level file
+ * reading. It is almost always better to use av_read_frame().
+ *
* @param s media file handle
* @param pkt is filled
- * @return 0 if OK. AVERROR_xxx if error.
+ * @return 0 if OK. AVERROR_xxx if error.
*/
int av_read_packet(AVFormatContext *s, AVPacket *pkt)
{
@@ -425,6 +448,7 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt)
}
}
+/*******************************************************/
/* return TRUE if the stream has accurate timings for at least one component */
static int av_has_timings(AVFormatContext *ic)
@@ -796,7 +820,7 @@ int av_find_stream_info(AVFormatContext *ic)
/* NOTE: if the format has no header, then we need to read
some packets to get most of the streams, so we cannot
stop here */
- if (!(ic->iformat->flags & AVFMT_NOHEADER) ||
+ if (!(ic->ctx_flags & AVFMTCTX_NOHEADER) ||
read_size >= min_read_size) {
/* if we found the info for all the codecs, we can stop */
ret = count;
@@ -821,12 +845,12 @@ int av_find_stream_info(AVFormatContext *ic)
ppktl = &pktl->next;
/* NOTE: a new stream can be added there if no header in file
- (AVFMT_NOHEADER) */
+ (AVFMTCTX_NOHEADER) */
pkt = &pktl->pkt;
if (ic->iformat->read_packet(ic, pkt) < 0) {
/* EOF or error */
ret = -1; /* we could not have all the codec parameters before EOF */
- if ((ic->iformat->flags & AVFMT_NOHEADER) &&
+ if ((ic->ctx_flags & AVFMTCTX_NOHEADER) &&
i == ic->nb_streams)
ret = 0;
break;
@@ -950,11 +974,14 @@ int av_find_stream_info(AVFormatContext *ic)
void av_close_input_file(AVFormatContext *s)
{
int i, must_open_file;
+ AVStream *st;
if (s->iformat->read_close)
s->iformat->read_close(s);
for(i=0;i<s->nb_streams;i++) {
- av_free(s->streams[i]);
+ /* free all data in a stream component */
+ st = s->streams[i];
+ av_free(st);
}
if (s->packet_buffer) {
AVPacketList *p, *p1;
@@ -968,11 +995,7 @@ void av_close_input_file(AVFormatContext *s)
s->packet_buffer = NULL;
}
must_open_file = 1;
- if ((s->iformat->flags & AVFMT_NOFILE)
-#ifdef CONFIG_NETWORK
- || (s->iformat == &rtp_demux && !strcmp(s->filename, "null"))
-#endif
- ) {
+ if (s->iformat->flags & AVFMT_NOFILE) {
must_open_file = 0;
}
if (must_open_file) {
@@ -984,12 +1007,12 @@ void av_close_input_file(AVFormatContext *s)
/**
* Add a new stream to a media file. Can only be called in the
- * read_header function. If the flag AVFMT_NOHEADER is in the format
- * description, then new streams can be added in read_packet too.
+ * read_header function. If the flag AVFMTCTX_NOHEADER is in the
+ * format context, then new streams can be added in read_packet too.
*
*
* @param s media file handle
- * @param id file format dependent stream id
+ * @param id file format dependent stream id
*/
AVStream *av_new_stream(AVFormatContext *s, int id)
{