1 /*
2 * audio.c:
3 * Attempt to extract audio frames embedded in buffers.
4 *
5 * We only try MPEG at the moment. Ogg Vorbis is a bit harder because we'd need
6 * to find the stream-start packet as well-- in practice, we probably would be
7 * able to, but it's a bit of a hassle.
8 *
9 * Copyright (c) 2002 Chris Lightfoot.
10 * Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
11 *
12 */
13
14 #ifdef HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17
18 #include "compat/compat.h"
19
20 #include <string.h>
21
22 #include "mpeghdr.h"
23
24 #include "audio.h"
25
26 /* The minimum chunk of MPEG data, in frames, which we accept. MPEG layer 2/3
27 * frames have 1152 samples, so there are something like 40 frames/s at
28 * 44.1kHz. If there are several MPEG streams available, driftnet may chop
29 * between them in chunks of this size. */
30 #define MIN_MPEG_EXTENT 100
31
32 /* find_mpeg_stream:
33 * Try to find some MPEG data in a stream. The game here is that we look for
34 * an MPEG audio header and see whether it's followed by a bunch more MPEG
35 * audio headers. If there's as much as MIN_MPEG_EXTEND data, then we give
36 * it back to the application and move our pointer on. */
find_mpeg_stream(const unsigned char * data,const size_t len,unsigned char ** mpegdata,size_t * mpeglen)37 unsigned char *find_mpeg_stream(const unsigned char *data, const size_t len, unsigned char **mpegdata, size_t *mpeglen) {
38 unsigned char *stream_start, *p;
39 struct mpeg_audio_hdr H;
40 *mpegdata = NULL;
41
42 if (len < 4) return (unsigned char*)data;
43 /*printf("find_mpeg_stream\n"); */
44 p = (unsigned char*)data;
45 while (p < data + len - 4) {
46 int nframes;
47 unsigned char *q;
48
49 /* Look for something which might be a frame header. */
50 stream_start = memchr(p, 0xff, len - 4 - (p - data));
51 if (!stream_start)
52 return (unsigned char*)(data + len - 4);
53
54 if ((stream_start[1] & 0xe0) != 0xe0) {
55 /*printf(" not followed by e0\n");*/
56 p = stream_start + 1;
57 continue;
58 }
59
60 /* OK, found something which might be a header.... */
61 if (!mpeg_hdr_parse(stream_start, &H)) {
62 p = stream_start + 1;
63 continue;
64 }
65
66 /* See how many frames we get. */
67 nframes = 0;
68 q = stream_start;
69 do {
70 int delta;
71 ++nframes;
72 delta = mpeg_hdr_nextframe_offset(&H);
73 if (delta == 0)
74 return q + 1;
75 q += delta;
76 } while (nframes < MIN_MPEG_EXTENT && q < data + len - 4 && mpeg_hdr_parse(q, &H));
77
78 if (nframes >= MIN_MPEG_EXTENT) {
79 /* got some data. */
80 /* printf("stream_start = %p, q = %p, len = %d\n", stream_start, q, q - stream_start);*/
81 *mpegdata = stream_start;
82 *mpeglen = q - stream_start;
83 return q;
84 } else
85 return stream_start;
86 }
87
88 return p;
89 }
90