• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/msnwc_tcp.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008  Ramiro Polla
00003  *
00004  * This file is part of Libav.
00005  *
00006  * Libav is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * Libav is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with Libav; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include "libavcodec/bytestream.h"
00022 #include "avformat.h"
00023 #include "internal.h"
00024 
00025 #define HEADER_SIZE         24
00026 
00027 /*
00028  * Header structure:
00029  *  uint16_t    ss;     // struct size
00030  *  uint16_t    width;  // frame width
00031  *  uint16_t    height; // frame height
00032  *  uint16_t    ff;     // keyframe + some other info(???)
00033  *  uint32_t    size;   // size of data
00034  *  uint32_t    fourcc; // ML20
00035  *  uint32_t    u3;     // ?
00036  *  uint32_t    ts;     // time
00037  */
00038 
00039 static int msnwc_tcp_probe(AVProbeData *p)
00040 {
00041     int i;
00042 
00043     for(i = 0 ; i + HEADER_SIZE <= p->buf_size ; i++) {
00044         uint16_t width, height;
00045         uint32_t fourcc;
00046         const uint8_t *bytestream = p->buf+i;
00047 
00048         if(bytestream_get_le16(&bytestream) != HEADER_SIZE)
00049             continue;
00050         width  = bytestream_get_le16(&bytestream);
00051         height = bytestream_get_le16(&bytestream);
00052         if(!(width==320 && height==240) && !(width==160 && height==120))
00053             continue;
00054         bytestream += 2; // keyframe
00055         bytestream += 4; // size
00056         fourcc = bytestream_get_le32(&bytestream);
00057         if(fourcc != MKTAG('M', 'L', '2', '0'))
00058             continue;
00059 
00060         if(i) {
00061             if(i < 14)  /* starts with SwitchBoard connection info */
00062                 return AVPROBE_SCORE_MAX / 2;
00063             else        /* starts in the middle of stream */
00064                 return AVPROBE_SCORE_MAX / 3;
00065         } else {
00066             return AVPROBE_SCORE_MAX;
00067         }
00068     }
00069 
00070     return -1;
00071 }
00072 
00073 static int msnwc_tcp_read_header(AVFormatContext *ctx, AVFormatParameters *ap)
00074 {
00075     AVIOContext *pb = ctx->pb;
00076     AVCodecContext *codec;
00077     AVStream *st;
00078 
00079     st = avformat_new_stream(ctx, NULL);
00080     if(!st)
00081         return AVERROR(ENOMEM);
00082 
00083     codec = st->codec;
00084     codec->codec_type = AVMEDIA_TYPE_VIDEO;
00085     codec->codec_id = CODEC_ID_MIMIC;
00086     codec->codec_tag = MKTAG('M', 'L', '2', '0');
00087 
00088     avpriv_set_pts_info(st, 32, 1, 1000);
00089 
00090     /* Some files start with "connected\r\n\r\n".
00091      * So skip until we find the first byte of struct size */
00092     while(avio_r8(pb) != HEADER_SIZE && !pb->eof_reached);
00093 
00094     if(pb->eof_reached) {
00095         av_log(ctx, AV_LOG_ERROR, "Could not find valid start.");
00096         return -1;
00097     }
00098 
00099     return 0;
00100 }
00101 
00102 static int msnwc_tcp_read_packet(AVFormatContext *ctx, AVPacket *pkt)
00103 {
00104     AVIOContext *pb = ctx->pb;
00105     uint16_t keyframe;
00106     uint32_t size, timestamp;
00107 
00108     avio_skip(pb, 1); /* one byte has been read ahead */
00109     avio_skip(pb, 2);
00110     avio_skip(pb, 2);
00111     keyframe = avio_rl16(pb);
00112     size = avio_rl32(pb);
00113     avio_skip(pb, 4);
00114     avio_skip(pb, 4);
00115     timestamp = avio_rl32(pb);
00116 
00117     if(!size || av_get_packet(pb, pkt, size) != size)
00118         return -1;
00119 
00120     avio_skip(pb, 1); /* Read ahead one byte of struct size like read_header */
00121 
00122     pkt->pts = timestamp;
00123     pkt->dts = timestamp;
00124     pkt->stream_index = 0;
00125 
00126     /* Some aMsn generated videos (or was it Mercury Messenger?) don't set
00127      * this bit and rely on the codec to get keyframe information */
00128     if(keyframe&1)
00129         pkt->flags |= AV_PKT_FLAG_KEY;
00130 
00131     return HEADER_SIZE + size;
00132 }
00133 
00134 AVInputFormat ff_msnwc_tcp_demuxer = {
00135     .name           = "msnwctcp",
00136     .long_name      = NULL_IF_CONFIG_SMALL("MSN TCP Webcam stream"),
00137     .read_probe     = msnwc_tcp_probe,
00138     .read_header    = msnwc_tcp_read_header,
00139     .read_packet    = msnwc_tcp_read_packet,
00140 };
Generated on Sun Apr 22 2012 21:54:07 for Libav by doxygen 1.7.1