]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/raw.c
flash video (flv) support patch by (Garrick Meeker <gmeeker at theoryllc dot com>)
[ffmpeg] / libavformat / raw.c
index 518206ea563532e33a14341295d1ead62a2fe68d..2354ad15cf84b9d26e83346a7328a49010ff50a5 100644 (file)
 #include "avformat.h"
 
 /* simple formats */
-int raw_write_header(struct AVFormatContext *s)
+static int raw_write_header(struct AVFormatContext *s)
 {
     return 0;
 }
 
-int raw_write_packet(struct AVFormatContext *s, 
-                     int stream_index,
-                     unsigned char *buf, int size, int force_pts)
+static int raw_write_packet(struct AVFormatContext *s, int stream_index,
+                           unsigned char *buf, int size, int force_pts)
 {
     put_buffer(&s->pb, buf, size);
     put_flush_packet(&s->pb);
     return 0;
 }
 
-int raw_write_trailer(struct AVFormatContext *s)
+static int raw_write_trailer(struct AVFormatContext *s)
 {
     return 0;
 }
 
 /* raw input */
-static int raw_read_header(AVFormatContext *s,
-                           AVFormatParameters *ap)
+static int raw_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     AVStream *st;
     int id;
@@ -63,9 +61,11 @@ static int raw_read_header(AVFormatContext *s,
             st->codec.channels = ap->channels;
             break;
         case CODEC_TYPE_VIDEO:
-            st->codec.frame_rate = ap->frame_rate;
+            st->codec.frame_rate      = ap->frame_rate;
+            st->codec.frame_rate_base = ap->frame_rate_base;
             st->codec.width = ap->width;
             st->codec.height = ap->height;
+           st->codec.pix_fmt = ap->pix_fmt;
             break;
         default:
             return -1;
@@ -78,11 +78,10 @@ static int raw_read_header(AVFormatContext *s,
 
 #define RAW_PACKET_SIZE 1024
 
-int raw_read_packet(AVFormatContext *s,
-                    AVPacket *pkt)
+static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     int ret, size;
-    AVStream *st = s->streams[0];
+    //    AVStream *st = s->streams[0];
     
     size= RAW_PACKET_SIZE;
 
@@ -101,7 +100,7 @@ int raw_read_packet(AVFormatContext *s,
     return ret;
 }
 
-int raw_read_close(AVFormatContext *s)
+static int raw_read_close(AVFormatContext *s)
 {
     return 0;
 }
@@ -111,6 +110,7 @@ static int mp3_read_header(AVFormatContext *s,
                            AVFormatParameters *ap)
 {
     AVStream *st;
+    int pos;
 
     st = av_new_stream(s, 0);
     if (!st)
@@ -118,6 +118,35 @@ static int mp3_read_header(AVFormatContext *s,
 
     st->codec.codec_type = CODEC_TYPE_AUDIO;
     st->codec.codec_id = CODEC_ID_MP2;
+
+    /* looking for 11111111 111MMLLC - MPEG synchronization tag
+       MM: 00 - MPEG-2.5, 10 - MPEG-2, 11 - MPEG-1
+       LL: 11 - Layer I, 10 - Layer II, 01 - Layer III
+       XXX: this code does not read more bytes from file 
+       so if ID3 (or other stuff) length > IO_BUFFER_SIZE it fails back to CODEC_ID_MP2 */
+    for(pos=0; pos < s->pb.buffer_size-1; pos++)
+       if( s->pb.buffer[pos] == 0xFF && (s->pb.buffer[pos] & 0xE0) == 0xE0 )
+           break;
+           
+    if( pos < s->pb.buffer_size-1 && (s->pb.buffer[pos+1] & 6) == 2 )
+       st->codec.codec_id = CODEC_ID_MP3LAME;
+
+    /* the parameters will be extracted from the compressed bitstream */
+    return 0;
+}
+
+/* ac3 read */
+static int ac3_read_header(AVFormatContext *s,
+                           AVFormatParameters *ap)
+{
+    AVStream *st;
+
+    st = av_new_stream(s, 0);
+    if (!st)
+        return AVERROR_NOMEM;
+
+    st->codec.codec_type = CODEC_TYPE_AUDIO;
+    st->codec.codec_id = CODEC_ID_AC3;
     /* the parameters will be extracted from the compressed bitstream */
     return 0;
 }
@@ -138,9 +167,11 @@ static int video_read_header(AVFormatContext *s,
     /* for mpeg4 specify it too (most mpeg4 streams dont have the fixed_vop_rate set ...)*/
     if (st->codec.codec_id == CODEC_ID_MJPEG || st->codec.codec_id == CODEC_ID_MPEG4) {
         if (ap) {
-            st->codec.frame_rate = ap->frame_rate;
+            st->codec.frame_rate      = ap->frame_rate;
+            st->codec.frame_rate_base = ap->frame_rate_base;
         } else {
-            st->codec.frame_rate = 25 * FRAME_RATE_BASE;
+            st->codec.frame_rate      = 25;
+            st->codec.frame_rate_base = 1;
         }
     }
     return 0;
@@ -153,27 +184,46 @@ static int video_read_header(AVFormatContext *s,
 /* XXX: improve that by looking at several start codes */
 static int mpegvideo_probe(AVProbeData *p)
 {
-    int code, c, i;
-    code = 0xff;
+    int code;
+    const uint8_t *d;
 
     /* we search the first start code. If it is a sequence, gop or
        picture start code then we decide it is an mpeg video
        stream. We do not send highest value to give a chance to mpegts */
-    for(i=0;i<p->buf_size;i++) {
-        c = p->buf[i];
-        code = (code << 8) | c;
-        if ((code & 0xffffff00) == 0x100) {
-            if (code == SEQ_START_CODE ||
-                code == GOP_START_CODE ||
-                code == PICTURE_START_CODE)
-                return 50 - 1;
-            else
-                return 0;
-        }
+    /* NOTE: the search range was restricted to avoid too many false
+       detections */
+
+    if (p->buf_size < 6)
+        return 0;
+    d = p->buf;
+    code = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | (d[3]);
+    if ((code & 0xffffff00) == 0x100) {
+        if (code == SEQ_START_CODE ||
+            code == GOP_START_CODE ||
+            code == PICTURE_START_CODE)
+            return 50 - 1;
+        else
+            return 0;
     }
     return 0;
 }
 
+static int h263_probe(AVProbeData *p)
+{
+    int code;
+    const uint8_t *d;
+
+    if (p->buf_size < 6)
+        return 0;
+    d = p->buf;
+    code = (d[0] << 14) | (d[1] << 6) | (d[2] >> 2);
+    if (code == 0x20) {
+        return 50;
+    }
+    return 0;
+}
+
+
 AVInputFormat mp3_iformat = {
     "mp3",
     "MPEG audio",
@@ -189,7 +239,11 @@ AVOutputFormat mp2_oformat = {
     "mp2",
     "MPEG audio layer 2",
     "audio/x-mpeg",
+#ifdef CONFIG_MP3LAME
+    "mp2",
+#else
     "mp2,mp3",
+#endif
     0,
     CODEC_ID_MP2,
     0,
@@ -198,17 +252,30 @@ AVOutputFormat mp2_oformat = {
     raw_write_trailer,
 };
 
+#ifdef CONFIG_MP3LAME
+AVOutputFormat mp3_oformat = {
+    "mp3",
+    "MPEG audio layer 3",
+    "audio/x-mpeg",
+    "mp3",
+    0,
+    CODEC_ID_MP3LAME,
+    0,
+    raw_write_header,
+    raw_write_packet,
+    raw_write_trailer,
+};
+#endif
 
 AVInputFormat ac3_iformat = {
     "ac3",
     "raw ac3",
     0,
     NULL,
-    raw_read_header,
+    ac3_read_header,
     raw_read_packet,
     raw_read_close,
     .extensions = "ac3",
-    .value = CODEC_ID_AC3,
 };
 
 AVOutputFormat ac3_oformat = {
@@ -224,6 +291,18 @@ AVOutputFormat ac3_oformat = {
     raw_write_trailer,
 };
 
+AVInputFormat h263_iformat = {
+    "h263",
+    "raw h263",
+    0,
+    h263_probe,
+    video_read_header,
+    raw_read_packet,
+    raw_read_close,
+//    .extensions = "h263", //FIXME remove after writing mpeg4_probe
+    .value = CODEC_ID_H263,
+};
+
 AVOutputFormat h263_oformat = {
     "h263",
     "raw h263",
@@ -262,6 +341,31 @@ AVOutputFormat m4v_oformat = {
     raw_write_trailer,
 };
 
+AVInputFormat h264_iformat = {
+    "h264",
+    "raw H264 video format",
+    0,
+    NULL /*mpegvideo_probe*/,
+    video_read_header,
+    raw_read_packet,
+    raw_read_close,
+    .extensions = "h26l,h264", //FIXME remove after writing mpeg4_probe
+    .value = CODEC_ID_H264,
+};
+
+AVOutputFormat h264_oformat = {
+    "h264",
+    "raw H264 video format",
+    NULL,
+    "h264",
+    0,
+    CODEC_ID_NONE,
+    CODEC_ID_H264,
+    raw_write_header,
+    raw_write_packet,
+    raw_write_trailer,
+};
+
 AVInputFormat mpegvideo_iformat = {
     "mpegvideo",
     "MPEG video",
@@ -372,8 +476,7 @@ PCMDEF(mulaw, "pcm mu law format",
 PCMDEF(alaw, "pcm A law format", 
        "al", CODEC_ID_PCM_ALAW)
 
-int rawvideo_read_packet(AVFormatContext *s,
-                         AVPacket *pkt)
+static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     int packet_size, ret, width, height;
     AVStream *st = s->streams[0];
@@ -381,21 +484,9 @@ int rawvideo_read_packet(AVFormatContext *s,
     width = st->codec.width;
     height = st->codec.height;
 
-    switch(st->codec.pix_fmt) {
-    case PIX_FMT_YUV420P:
-        packet_size = (width * height * 3) / 2;
-        break;
-    case PIX_FMT_YUV422:
-        packet_size = (width * height * 2);
-        break;
-    case PIX_FMT_BGR24:
-    case PIX_FMT_RGB24:
-        packet_size = (width * height * 3);
-        break;
-    default:
+    packet_size = avpicture_get_size(st->codec.pix_fmt, width, height);
+    if (packet_size < 0)
         av_abort();
-        break;
-    }
 
     if (av_new_packet(pkt, packet_size) < 0)
         return -EIO;
@@ -469,14 +560,20 @@ int raw_init(void)
 {
     av_register_input_format(&mp3_iformat);
     av_register_output_format(&mp2_oformat);
-    
+#ifdef CONFIG_MP3LAME
+    av_register_output_format(&mp3_oformat);
+#endif    
     av_register_input_format(&ac3_iformat);
     av_register_output_format(&ac3_oformat);
 
+    av_register_input_format(&h263_iformat);
     av_register_output_format(&h263_oformat);
     
     av_register_input_format(&m4v_iformat);
     av_register_output_format(&m4v_oformat);
+    
+    av_register_input_format(&h264_iformat);
+    av_register_output_format(&h264_oformat);
 
     av_register_input_format(&mpegvideo_iformat);
     av_register_output_format(&mpeg1video_oformat);