Libav 0.7.1
|
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 00024 #define HEADER_SIZE 24 00025 00026 /* 00027 * Header structure: 00028 * uint16_t ss; // struct size 00029 * uint16_t width; // frame width 00030 * uint16_t height; // frame height 00031 * uint16_t ff; // keyframe + some other info(???) 00032 * uint32_t size; // size of data 00033 * uint32_t fourcc; // ML20 00034 * uint32_t u3; // ? 00035 * uint32_t ts; // time 00036 */ 00037 00038 static int msnwc_tcp_probe(AVProbeData *p) 00039 { 00040 int i; 00041 00042 for(i = 0 ; i + HEADER_SIZE <= p->buf_size ; i++) { 00043 uint16_t width, height; 00044 uint32_t fourcc; 00045 const uint8_t *bytestream = p->buf+i; 00046 00047 if(bytestream_get_le16(&bytestream) != HEADER_SIZE) 00048 continue; 00049 width = bytestream_get_le16(&bytestream); 00050 height = bytestream_get_le16(&bytestream); 00051 if(!(width==320 && height==240) && !(width==160 && height==120)) 00052 continue; 00053 bytestream += 2; // keyframe 00054 bytestream += 4; // size 00055 fourcc = bytestream_get_le32(&bytestream); 00056 if(fourcc != MKTAG('M', 'L', '2', '0')) 00057 continue; 00058 00059 if(i) { 00060 if(i < 14) /* starts with SwitchBoard connection info */ 00061 return AVPROBE_SCORE_MAX / 2; 00062 else /* starts in the middle of stream */ 00063 return AVPROBE_SCORE_MAX / 3; 00064 } else { 00065 return AVPROBE_SCORE_MAX; 00066 } 00067 } 00068 00069 return -1; 00070 } 00071 00072 static int msnwc_tcp_read_header(AVFormatContext *ctx, AVFormatParameters *ap) 00073 { 00074 AVIOContext *pb = ctx->pb; 00075 AVCodecContext *codec; 00076 AVStream *st; 00077 00078 st = av_new_stream(ctx, 0); 00079 if(!st) 00080 return AVERROR(ENOMEM); 00081 00082 codec = st->codec; 00083 codec->codec_type = AVMEDIA_TYPE_VIDEO; 00084 codec->codec_id = CODEC_ID_MIMIC; 00085 codec->codec_tag = MKTAG('M', 'L', '2', '0'); 00086 00087 av_set_pts_info(st, 32, 1, 1000); 00088 00089 /* Some files start with "connected\r\n\r\n". 00090 * So skip until we find the first byte of struct size */ 00091 while(avio_r8(pb) != HEADER_SIZE && !pb->eof_reached); 00092 00093 if(pb->eof_reached) { 00094 av_log(ctx, AV_LOG_ERROR, "Could not find valid start."); 00095 return -1; 00096 } 00097 00098 return 0; 00099 } 00100 00101 static int msnwc_tcp_read_packet(AVFormatContext *ctx, AVPacket *pkt) 00102 { 00103 AVIOContext *pb = ctx->pb; 00104 uint16_t keyframe; 00105 uint32_t size, timestamp; 00106 00107 avio_skip(pb, 1); /* one byte has been read ahead */ 00108 avio_skip(pb, 2); 00109 avio_skip(pb, 2); 00110 keyframe = avio_rl16(pb); 00111 size = avio_rl32(pb); 00112 avio_skip(pb, 4); 00113 avio_skip(pb, 4); 00114 timestamp = avio_rl32(pb); 00115 00116 if(!size || av_get_packet(pb, pkt, size) != size) 00117 return -1; 00118 00119 avio_skip(pb, 1); /* Read ahead one byte of struct size like read_header */ 00120 00121 pkt->pts = timestamp; 00122 pkt->dts = timestamp; 00123 pkt->stream_index = 0; 00124 00125 /* Some aMsn generated videos (or was it Mercury Messenger?) don't set 00126 * this bit and rely on the codec to get keyframe information */ 00127 if(keyframe&1) 00128 pkt->flags |= AV_PKT_FLAG_KEY; 00129 00130 return HEADER_SIZE + size; 00131 } 00132 00133 AVInputFormat ff_msnwc_tcp_demuxer = { 00134 "msnwctcp", 00135 NULL_IF_CONFIG_SMALL("MSN TCP Webcam stream"), 00136 0, 00137 msnwc_tcp_probe, 00138 msnwc_tcp_read_header, 00139 msnwc_tcp_read_packet, 00140 };