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