00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #include "libavcodec/bytestream.h"
00022 #include "avformat.h"
00023 #include "internal.h"
00024 
00025 #define HEADER_SIZE         24
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
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; 
00055         bytestream += 4; 
00056         fourcc = bytestream_get_le32(&bytestream);
00057         if(fourcc != MKTAG('M', 'L', '2', '0'))
00058             continue;
00059 
00060         if(i) {
00061             if(i < 14)  
00062                 return AVPROBE_SCORE_MAX / 2;
00063             else        
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     
00091 
00092     while(avio_r8(pb) != HEADER_SIZE && !url_feof(pb));
00093 
00094     if(url_feof(pb)) {
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); 
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); 
00121 
00122     pkt->pts = timestamp;
00123     pkt->dts = timestamp;
00124     pkt->stream_index = 0;
00125 
00126     
00127 
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 };