Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (C) 2008  Ramiro Polla
  3.  *
  4.  * This file is part of FFmpeg.
  5.  *
  6.  * FFmpeg is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * FFmpeg is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with FFmpeg; if not, write to the Free Software
  18.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19.  */
  20.  
  21. #include "libavcodec/bytestream.h"
  22. #include "avformat.h"
  23. #include "internal.h"
  24.  
  25. #define HEADER_SIZE         24
  26.  
  27. /*
  28.  * Header structure:
  29.  *  uint16_t    ss;     // struct size
  30.  *  uint16_t    width;  // frame width
  31.  *  uint16_t    height; // frame height
  32.  *  uint16_t    ff;     // keyframe + some other info(???)
  33.  *  uint32_t    size;   // size of data
  34.  *  uint32_t    fourcc; // ML20
  35.  *  uint32_t    u3;     // ?
  36.  *  uint32_t    ts;     // time
  37.  */
  38.  
  39. static int msnwc_tcp_probe(AVProbeData *p)
  40. {
  41.     int i;
  42.  
  43.     for(i = 0 ; i + HEADER_SIZE <= p->buf_size ; i++) {
  44.         uint16_t width, height;
  45.         uint32_t fourcc;
  46.         const uint8_t *bytestream = p->buf+i;
  47.  
  48.         if(bytestream_get_le16(&bytestream) != HEADER_SIZE)
  49.             continue;
  50.         width  = bytestream_get_le16(&bytestream);
  51.         height = bytestream_get_le16(&bytestream);
  52.         if(!(width==320 && height==240) && !(width==160 && height==120))
  53.             continue;
  54.         bytestream += 2; // keyframe
  55.         bytestream += 4; // size
  56.         fourcc = bytestream_get_le32(&bytestream);
  57.         if(fourcc != MKTAG('M', 'L', '2', '0'))
  58.             continue;
  59.  
  60.         if(i) {
  61.             if(i < 14)  /* starts with SwitchBoard connection info */
  62.                 return AVPROBE_SCORE_MAX / 2;
  63.             else        /* starts in the middle of stream */
  64.                 return AVPROBE_SCORE_MAX / 3;
  65.         } else {
  66.             return AVPROBE_SCORE_MAX;
  67.         }
  68.     }
  69.  
  70.     return -1;
  71. }
  72.  
  73. static int msnwc_tcp_read_header(AVFormatContext *ctx)
  74. {
  75.     AVIOContext *pb = ctx->pb;
  76.     AVCodecContext *codec;
  77.     AVStream *st;
  78.  
  79.     st = avformat_new_stream(ctx, NULL);
  80.     if(!st)
  81.         return AVERROR(ENOMEM);
  82.  
  83.     codec = st->codec;
  84.     codec->codec_type = AVMEDIA_TYPE_VIDEO;
  85.     codec->codec_id = AV_CODEC_ID_MIMIC;
  86.     codec->codec_tag = MKTAG('M', 'L', '2', '0');
  87.  
  88.     avpriv_set_pts_info(st, 32, 1, 1000);
  89.  
  90.     /* Some files start with "connected\r\n\r\n".
  91.      * So skip until we find the first byte of struct size */
  92.     while(avio_r8(pb) != HEADER_SIZE && !url_feof(pb));
  93.  
  94.     if(url_feof(pb)) {
  95.         av_log(ctx, AV_LOG_ERROR, "Could not find valid start.\n");
  96.         return -1;
  97.     }
  98.  
  99.     return 0;
  100. }
  101.  
  102. static int msnwc_tcp_read_packet(AVFormatContext *ctx, AVPacket *pkt)
  103. {
  104.     AVIOContext *pb = ctx->pb;
  105.     uint16_t keyframe;
  106.     uint32_t size, timestamp;
  107.  
  108.     avio_skip(pb, 1); /* one byte has been read ahead */
  109.     avio_skip(pb, 2);
  110.     avio_skip(pb, 2);
  111.     keyframe = avio_rl16(pb);
  112.     size = avio_rl32(pb);
  113.     avio_skip(pb, 4);
  114.     avio_skip(pb, 4);
  115.     timestamp = avio_rl32(pb);
  116.  
  117.     if(!size || av_get_packet(pb, pkt, size) != size)
  118.         return -1;
  119.  
  120.     avio_skip(pb, 1); /* Read ahead one byte of struct size like read_header */
  121.  
  122.     pkt->pts = timestamp;
  123.     pkt->dts = timestamp;
  124.     pkt->stream_index = 0;
  125.  
  126.     /* Some aMsn generated videos (or was it Mercury Messenger?) don't set
  127.      * this bit and rely on the codec to get keyframe information */
  128.     if(keyframe&1)
  129.         pkt->flags |= AV_PKT_FLAG_KEY;
  130.  
  131.     return HEADER_SIZE + size;
  132. }
  133.  
  134. AVInputFormat ff_msnwc_tcp_demuxer = {
  135.     .name           = "msnwctcp",
  136.     .long_name      = NULL_IF_CONFIG_SMALL("MSN TCP Webcam stream"),
  137.     .read_probe     = msnwc_tcp_probe,
  138.     .read_header    = msnwc_tcp_read_header,
  139.     .read_packet    = msnwc_tcp_read_packet,
  140. };
  141.