FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/msnwc_tcp.c
Date: 2024-04-17 23:49:55
Exec Total Coverage
Lines: 50 57 87.7%
Functions: 3 3 100.0%
Branches: 20 32 62.5%

Line Branch Exec Source
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 "demux.h"
24 #include "internal.h"
25
26 #define HEADER_SIZE 24
27
28 /*
29 * Header structure:
30 * uint16_t ss; // struct size
31 * uint16_t width; // frame width
32 * uint16_t height; // frame height
33 * uint16_t ff; // keyframe + some other info(???)
34 * uint32_t size; // size of data
35 * uint32_t fourcc; // ML20
36 * uint32_t u3; // ?
37 * uint32_t ts; // time
38 */
39
40 7125 static int msnwc_tcp_probe(const AVProbeData *p)
41 {
42 int i;
43
44
2/2
✓ Branch 0 taken 367413024 times.
✓ Branch 1 taken 7124 times.
367420148 for (i = 0; i + HEADER_SIZE <= p->buf_size; i++) {
45 uint16_t width, height;
46 uint32_t fourcc;
47 367413024 const uint8_t *bytestream = p->buf + i;
48
49
2/2
✓ Branch 1 taken 367343852 times.
✓ Branch 2 taken 69172 times.
367413024 if (bytestream_get_le16(&bytestream) != HEADER_SIZE)
50 367413023 continue;
51 69172 width = bytestream_get_le16(&bytestream);
52 69172 height = bytestream_get_le16(&bytestream);
53
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 69171 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
69172 if (!(width == 320 &&
54
3/4
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 69088 times.
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
69171 height == 240) && !(width == 160 && height == 120))
55 69171 continue;
56 1 bytestream += 2; // keyframe
57 1 bytestream += 4; // size
58 1 fourcc = bytestream_get_le32(&bytestream);
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (fourcc != MKTAG('M', 'L', '2', '0'))
60 continue;
61
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (i) {
63 if (i < 14) /* starts with SwitchBoard connection info */
64 1 return AVPROBE_SCORE_MAX / 2;
65 else /* starts in the middle of stream */
66 return AVPROBE_SCORE_MAX / 3;
67 } else {
68 1 return AVPROBE_SCORE_MAX;
69 }
70 }
71
72 7124 return 0;
73 }
74
75 1 static int msnwc_tcp_read_header(AVFormatContext *ctx)
76 {
77 1 AVIOContext *pb = ctx->pb;
78 AVCodecParameters *par;
79 AVStream *st;
80
81 1 st = avformat_new_stream(ctx, NULL);
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!st)
83 return AVERROR(ENOMEM);
84
85 1 par = st->codecpar;
86 1 par->codec_type = AVMEDIA_TYPE_VIDEO;
87 1 par->codec_id = AV_CODEC_ID_MIMIC;
88 1 par->codec_tag = MKTAG('M', 'L', '2', '0');
89
90 1 avpriv_set_pts_info(st, 32, 1, 1000);
91
92 /* Some files start with "connected\r\n\r\n".
93 * So skip until we find the first byte of struct size */
94
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 while(avio_r8(pb) != HEADER_SIZE && !avio_feof(pb)) ;
95
96
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if(avio_feof(pb)) {
97 av_log(ctx, AV_LOG_ERROR, "Could not find valid start.\n");
98 return AVERROR_INVALIDDATA;
99 }
100
101 1 return 0;
102 }
103
104 77 static int msnwc_tcp_read_packet(AVFormatContext *ctx, AVPacket *pkt)
105 {
106 77 AVIOContext *pb = ctx->pb;
107 uint16_t keyframe;
108 uint32_t size, timestamp;
109 int ret;
110
111 77 avio_skip(pb, 1); /* one byte has been read ahead */
112 77 avio_skip(pb, 2);
113 77 avio_skip(pb, 2);
114 77 keyframe = avio_rl16(pb);
115 77 size = avio_rl32(pb);
116 77 avio_skip(pb, 4);
117 77 avio_skip(pb, 4);
118 77 timestamp = avio_rl32(pb);
119
120
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 76 times.
77 if (!size)
121 1 return AVERROR_INVALIDDATA;
122
123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
76 if ((ret = av_get_packet(pb, pkt, size)) < 0)
124 return ret;
125
126 76 avio_skip(pb, 1); /* Read ahead one byte of struct size like read_header */
127
128 76 pkt->pts = timestamp;
129 76 pkt->dts = timestamp;
130 76 pkt->stream_index = 0;
131
132 /* Some aMsn generated videos (or was it Mercury Messenger?) don't set
133 * this bit and rely on the codec to get keyframe information */
134
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 74 times.
76 if (keyframe & 1)
135 2 pkt->flags |= AV_PKT_FLAG_KEY;
136
137 76 return HEADER_SIZE + size;
138 }
139
140 const FFInputFormat ff_msnwc_tcp_demuxer = {
141 .p.name = "msnwctcp",
142 .p.long_name = NULL_IF_CONFIG_SMALL("MSN TCP Webcam stream"),
143 .read_probe = msnwc_tcp_probe,
144 .read_header = msnwc_tcp_read_header,
145 .read_packet = msnwc_tcp_read_packet,
146 };
147