Commit da24c5e3 authored by Fabrice Bellard's avatar Fabrice Bellard

make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()

Originally committed as revision 2447 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent b45a7a18
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
extern "C" { extern "C" {
#endif #endif
#define LIBAVFORMAT_BUILD 4608 #define LIBAVFORMAT_BUILD 4609
#define LIBAVFORMAT_VERSION_INT FFMPEG_VERSION_INT #define LIBAVFORMAT_VERSION_INT FFMPEG_VERSION_INT
#define LIBAVFORMAT_VERSION FFMPEG_VERSION #define LIBAVFORMAT_VERSION FFMPEG_VERSION
...@@ -42,6 +42,7 @@ typedef struct AVPacket { ...@@ -42,6 +42,7 @@ typedef struct AVPacket {
} AVPacket; } AVPacket;
#define PKT_FLAG_KEY 0x0001 #define PKT_FLAG_KEY 0x0001
/* initialize optional fields of a packet */
static inline void av_init_packet(AVPacket *pkt) static inline void av_init_packet(AVPacket *pkt)
{ {
pkt->pts = AV_NOPTS_VALUE; pkt->pts = AV_NOPTS_VALUE;
...@@ -102,12 +103,14 @@ typedef struct AVFormatParameters { ...@@ -102,12 +103,14 @@ typedef struct AVFormatParameters {
int channel; /* used to select dv channel */ int channel; /* used to select dv channel */
const char *device; /* video4linux, audio or DV device */ const char *device; /* video4linux, audio or DV device */
const char *standard; /* tv standard, NTSC, PAL, SECAM */ 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; } AVFormatParameters;
#define AVFMT_NOFILE 0x0001 /* no file should be opened */ #define AVFMT_NOFILE 0x0001 /* no file should be opened */
#define AVFMT_NEEDNUMBER 0x0002 /* needs '%d' in filename */ #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_SHOW_IDS 0x0008 /* show format stream IDs numbers */
#define AVFMT_RAWPICTURE 0x0020 /* format wants AVPicture structure for #define AVFMT_RAWPICTURE 0x0020 /* format wants AVPicture structure for
raw picture data */ raw picture data */
...@@ -150,7 +153,7 @@ typedef struct AVInputFormat { ...@@ -150,7 +153,7 @@ typedef struct AVInputFormat {
AVFormatParameters *ap); AVFormatParameters *ap);
/* read one packet and put it in 'pkt'. pts and flags are also /* read one packet and put it in 'pkt'. pts and flags are also
set. 'av_new_stream' can be called only if the flag 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); int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
/* close the stream. The AVFormatContext and AVStreams are not /* close the stream. The AVFormatContext and AVStreams are not
freed by this function */ freed by this function */
...@@ -158,7 +161,7 @@ typedef struct AVInputFormat { ...@@ -158,7 +161,7 @@ typedef struct AVInputFormat {
/* seek at or before a given pts (given in microsecond). The pts /* seek at or before a given pts (given in microsecond). The pts
origin is defined by the stream */ origin is defined by the stream */
int (*read_seek)(struct AVFormatContext *, int64_t pts); 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; int flags;
/* if extensions are defined, then no probe is done. You should /* if extensions are defined, then no probe is done. You should
usually not use extension format guessing because it is not usually not use extension format guessing because it is not
...@@ -181,7 +184,7 @@ typedef struct AVStream { ...@@ -181,7 +184,7 @@ typedef struct AVStream {
int codec_info_state; int codec_info_state;
int codec_info_nb_repeat_frames; int codec_info_nb_repeat_frames;
int codec_info_nb_real_frames; int codec_info_nb_real_frames;
/* PTS generation when outputing stream */ /* encoding: PTS generation when outputing stream */
AVFrac pts; AVFrac pts;
/* ffmpeg.c private use */ /* ffmpeg.c private use */
int stream_copy; /* if TRUE, just copy stream */ int stream_copy; /* if TRUE, just copy stream */
...@@ -196,6 +199,9 @@ typedef struct AVStream { ...@@ -196,6 +199,9 @@ typedef struct AVStream {
int64_t duration; int64_t duration;
} AVStream; } AVStream;
#define AVFMTCTX_NOHEADER 0x0001 /* signal that no header is present
(streams are added dynamically) */
#define MAX_STREAMS 20 #define MAX_STREAMS 20
/* format I/O context */ /* format I/O context */
...@@ -218,7 +224,7 @@ typedef struct AVFormatContext { ...@@ -218,7 +224,7 @@ typedef struct AVFormatContext {
int track; /* track number, 0 if none */ int track; /* track number, 0 if none */
char genre[32]; /* ID3 genre */ 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) */ /* private data for pts handling (do not modify directly) */
int pts_wrap_bits; /* number of bits in pts (used for wrapping control) */ int pts_wrap_bits; /* number of bits in pts (used for wrapping control) */
int pts_num, pts_den; /* value to convert to seconds */ 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); ...@@ -448,6 +454,9 @@ void fifo_write(FifoBuffer *f, uint8_t *buf, int size, uint8_t **wptr_ptr);
/* media file input */ /* media file input */
AVInputFormat *av_find_input_format(const char *short_name); AVInputFormat *av_find_input_format(const char *short_name);
AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened); 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, int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
AVInputFormat *fmt, AVInputFormat *fmt,
int buf_size, int buf_size,
......
...@@ -479,6 +479,8 @@ static int mpegps_read_header(AVFormatContext *s, ...@@ -479,6 +479,8 @@ static int mpegps_read_header(AVFormatContext *s,
{ {
MpegDemuxContext *m = s->priv_data; MpegDemuxContext *m = s->priv_data;
m->header_state = 0xff; m->header_state = 0xff;
s->ctx_flags |= AVFMTCTX_NOHEADER;
/* no need to do more */ /* no need to do more */
return 0; return 0;
} }
...@@ -705,7 +707,6 @@ AVInputFormat mpegps_demux = { ...@@ -705,7 +707,6 @@ AVInputFormat mpegps_demux = {
mpegps_read_header, mpegps_read_header,
mpegps_read_packet, mpegps_read_packet,
mpegps_read_close, mpegps_read_close,
.flags = AVFMT_NOHEADER,
}; };
int mpegps_init(void) int mpegps_init(void)
......
...@@ -274,6 +274,56 @@ AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened) ...@@ -274,6 +274,56 @@ AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)
/************************************************************/ /************************************************************/
/* input media file */ /* 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 #define PROBE_BUF_SIZE 2048
/** /**
...@@ -292,20 +342,15 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, ...@@ -292,20 +342,15 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
int buf_size, int buf_size,
AVFormatParameters *ap) AVFormatParameters *ap)
{ {
AVFormatContext *ic = NULL; int err, must_open_file, file_opened;
int err, must_open_file; uint8_t buf[PROBE_BUF_SIZE];
unsigned char buf[PROBE_BUF_SIZE];
AVProbeData probe_data, *pd = &probe_data; AVProbeData probe_data, *pd = &probe_data;
ByteIOContext pb1, *pb = &pb1;
ic = av_mallocz(sizeof(AVFormatContext));
if (!ic) { file_opened = 0;
err = AVERROR_NOMEM; pd->filename = "";
goto fail; if (filename)
} pd->filename = filename;
ic->duration = AV_NOPTS_VALUE;
ic->start_time = AV_NOPTS_VALUE;
pstrcpy(ic->filename, sizeof(ic->filename), filename);
pd->filename = ic->filename;
pd->buf = buf; pd->buf = buf;
pd->buf_size = 0; pd->buf_size = 0;
...@@ -317,27 +362,24 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, ...@@ -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 /* do not open file if the format does not need it. XXX: specific
hack needed to handle RTSP/TCP */ hack needed to handle RTSP/TCP */
must_open_file = 1; must_open_file = 1;
if ((fmt && (fmt->flags & AVFMT_NOFILE)) if (fmt && (fmt->flags & AVFMT_NOFILE)) {
#ifdef CONFIG_NETWORK
|| (fmt == &rtp_demux && !strcmp(filename, "null"))
#endif
) {
must_open_file = 0; must_open_file = 0;
} }
if (!fmt || must_open_file) { if (!fmt || must_open_file) {
/* if no file needed do not try to open one */ /* 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; err = AVERROR_IO;
goto fail; goto fail;
} }
file_opened = 1;
if (buf_size > 0) { if (buf_size > 0) {
url_setbufsize(&ic->pb, buf_size); url_setbufsize(pb, buf_size);
} }
if (!fmt) { if (!fmt) {
/* read probe data */ /* read probe data */
pd->buf_size = get_buffer(&ic->pb, buf, PROBE_BUF_SIZE); pd->buf_size = get_buffer(pb, buf, PROBE_BUF_SIZE);
url_fseek(&ic->pb, 0, SEEK_SET); url_fseek(pb, 0, SEEK_SET);
} }
} }
...@@ -349,65 +391,46 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, ...@@ -349,65 +391,46 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
/* if still no format found, error */ /* if still no format found, error */
if (!fmt) { if (!fmt) {
err = AVERROR_NOFMT; err = AVERROR_NOFMT;
goto fail1; goto fail;
} }
/* XXX: suppress this hack for redirectors */ /* XXX: suppress this hack for redirectors */
#ifdef CONFIG_NETWORK #ifdef CONFIG_NETWORK
if (fmt == &redir_demux) { if (fmt == &redir_demux) {
err = redir_open(ic_ptr, &ic->pb); err = redir_open(ic_ptr, pb);
url_fclose(&ic->pb); url_fclose(pb);
av_free(ic);
return err; return err;
} }
#endif #endif
ic->iformat = fmt;
/* check filename in case of an image number is expected */ /* check filename in case of an image number is expected */
if (ic->iformat->flags & AVFMT_NEEDNUMBER) { if (fmt->flags & AVFMT_NEEDNUMBER) {
if (filename_number_test(ic->filename) < 0) { if (filename_number_test(filename) < 0) {
err = AVERROR_NUMEXPECTED; err = AVERROR_NUMEXPECTED;
goto fail1; goto fail;
} }
} }
err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);
/* allocate private data */ if (err)
if (fmt->priv_data_size > 0) { goto fail;
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;
return 0; return 0;
fail1:
if (!fmt || must_open_file) {
url_fclose(&ic->pb);
}
fail: fail:
if (ic) { if (file_opened)
av_freep(&ic->priv_data); url_fclose(pb);
}
av_free(ic);
*ic_ptr = NULL; *ic_ptr = NULL;
return err; 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 s media file handle
* @param pkt is filled * @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) int av_read_packet(AVFormatContext *s, AVPacket *pkt)
{ {
...@@ -425,6 +448,7 @@ 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 */ /* return TRUE if the stream has accurate timings for at least one component */
static int av_has_timings(AVFormatContext *ic) static int av_has_timings(AVFormatContext *ic)
...@@ -796,7 +820,7 @@ int av_find_stream_info(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 /* NOTE: if the format has no header, then we need to read
some packets to get most of the streams, so we cannot some packets to get most of the streams, so we cannot
stop here */ stop here */
if (!(ic->iformat->flags & AVFMT_NOHEADER) || if (!(ic->ctx_flags & AVFMTCTX_NOHEADER) ||
read_size >= min_read_size) { read_size >= min_read_size) {
/* if we found the info for all the codecs, we can stop */ /* if we found the info for all the codecs, we can stop */
ret = count; ret = count;
...@@ -821,12 +845,12 @@ int av_find_stream_info(AVFormatContext *ic) ...@@ -821,12 +845,12 @@ int av_find_stream_info(AVFormatContext *ic)
ppktl = &pktl->next; ppktl = &pktl->next;
/* NOTE: a new stream can be added there if no header in file /* NOTE: a new stream can be added there if no header in file
(AVFMT_NOHEADER) */ (AVFMTCTX_NOHEADER) */
pkt = &pktl->pkt; pkt = &pktl->pkt;
if (ic->iformat->read_packet(ic, pkt) < 0) { if (ic->iformat->read_packet(ic, pkt) < 0) {
/* EOF or error */ /* EOF or error */
ret = -1; /* we could not have all the codec parameters before EOF */ 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) i == ic->nb_streams)
ret = 0; ret = 0;
break; break;
...@@ -950,11 +974,14 @@ int av_find_stream_info(AVFormatContext *ic) ...@@ -950,11 +974,14 @@ int av_find_stream_info(AVFormatContext *ic)
void av_close_input_file(AVFormatContext *s) void av_close_input_file(AVFormatContext *s)
{ {
int i, must_open_file; int i, must_open_file;
AVStream *st;
if (s->iformat->read_close) if (s->iformat->read_close)
s->iformat->read_close(s); s->iformat->read_close(s);
for(i=0;i<s->nb_streams;i++) { 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) { if (s->packet_buffer) {
AVPacketList *p, *p1; AVPacketList *p, *p1;
...@@ -968,11 +995,7 @@ void av_close_input_file(AVFormatContext *s) ...@@ -968,11 +995,7 @@ void av_close_input_file(AVFormatContext *s)
s->packet_buffer = NULL; s->packet_buffer = NULL;
} }
must_open_file = 1; must_open_file = 1;
if ((s->iformat->flags & AVFMT_NOFILE) if (s->iformat->flags & AVFMT_NOFILE) {
#ifdef CONFIG_NETWORK
|| (s->iformat == &rtp_demux && !strcmp(s->filename, "null"))
#endif
) {
must_open_file = 0; must_open_file = 0;
} }
if (must_open_file) { if (must_open_file) {
...@@ -984,12 +1007,12 @@ void av_close_input_file(AVFormatContext *s) ...@@ -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 * 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 * read_header function. If the flag AVFMTCTX_NOHEADER is in the
* description, then new streams can be added in read_packet too. * format context, then new streams can be added in read_packet too.
* *
* *
* @param s media file handle * @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) AVStream *av_new_stream(AVFormatContext *s, int id)
{ {
......
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