mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()
Originally committed as revision 2447 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
b45a7a18d3
commit
da24c5e330
@ -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 {
|
|||||||
} 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
/* 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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);
|
|||||||
/* 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,
|
|||||||
{
|
{
|
||||||
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 = {
|
|||||||
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)
|
|||||||
/************************************************************/
|
/************************************************************/
|
||||||
/* 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,
|
|||||||
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));
|
file_opened = 0;
|
||||||
if (!ic) {
|
pd->filename = "";
|
||||||
err = AVERROR_NOMEM;
|
if (filename)
|
||||||
goto fail;
|
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,
|
|||||||
/* 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,62 +391,43 @@ 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.
|
||||||
@ -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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,8 +1007,8 @@ 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
|
||||||
|
Loading…
Reference in New Issue
Block a user