make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()
authorFabrice Bellard <fabrice@bellard.org>
Wed, 29 Oct 2003 14:20:56 +0000 (14:20 +0000)
committerFabrice Bellard <fabrice@bellard.org>
Wed, 29 Oct 2003 14:20:56 +0000 (14:20 +0000)
Originally committed as revision 2447 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/avformat.h
libavformat/mpeg.c
libavformat/utils.c

index 7de9c8e..f3a89fd 100644 (file)
@@ -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,
index 45ffdf6..9c13855 100644 (file)
@@ -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)
index 70c9e6e..ddd26f1 100644 (file)
@@ -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)
 {