2009-12-01 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / src / mp3.h
blob1192cdf0160c4c4b140bc6eb7f17bf54362f6f6b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * mp3.h: Mp3 for the media
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2008 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
14 #ifndef __MOON_MP3_H_
15 #define __MOON_MP3_H_
17 #include <glib.h>
19 #include "pipeline.h"
22 /* validate that this is an MPEG audio stream by checking that
23 * the 32bit header matches the pattern:
25 * 1111 1111 111* **** **** **** **** **** = 0xff 0xe0
27 * Use a mask of 0xffe6 (because bits 12 and 13 can both be 0 if it is
28 * MPEG 2.5). Compare the second byte > 0xe0 because one of the other
29 * masked bits has to be set (the Layer bits cannot both be 0).
31 #define is_mpeg_header(buffer) (buffer[0] == 0xff && ((buffer[1] & 0xe6) > 0xe0) && (buffer[1] & 0x18) != 0x08)
33 struct MpegFrameHeader {
34 guint8 version:2;
35 guint8 layer:2;
37 guint8 copyright:1;
38 guint8 original:1;
39 guint8 padded:1;
40 guint8 prot:1;
42 guint8 channels:6;
43 guint8 intensity:1;
44 guint8 ms:1;
46 gint32 bit_rate;
47 gint32 sample_rate;
50 enum MpegVBRHeaderType {
51 MpegNoVBRHeader,
52 MpegXingHeader,
53 MpegVBRIHeader
56 struct MpegVBRHeader {
57 MpegVBRHeaderType type;
58 guint32 nframes;
61 struct MpegFrame {
62 gint64 offset;
63 guint64 pts;
64 guint32 dur;
66 // this is needed in case this frame did not specify it's own
67 // bit rate which is possible for MPEG-1 Layer 3 audio.
68 gint32 bit_rate;
71 class Mp3FrameReader {
72 IMediaSource *source;
73 AudioStream *stream;
74 gint64 stream_start;
75 guint32 frame_dur;
76 guint32 frame_len;
77 guint64 cur_pts;
78 gint32 bit_rate;
79 bool xing;
80 bool sync_lost;
82 MpegFrame *jmptab;
83 guint32 avail;
84 guint32 used;
86 guint32 MpegFrameSearch (guint64 pts);
87 void AddFrameIndex (gint64 offset, guint64 pts, guint32 dur, gint32 bit_rate);
89 MediaResult SkipFrame ();
91 public:
92 Mp3FrameReader (IMediaSource *source, AudioStream *stream, gint64 start, guint32 frame_len, guint32 frame_duration, bool xing);
93 ~Mp3FrameReader ();
95 MediaResult Seek (guint64 pts);
97 MediaResult TryReadFrame (MediaFrame **frame);
99 // FindMpegHeader
100 // Might change the current position of the source
101 static MediaResult FindMpegHeader (MpegFrameHeader *mpeg, MpegVBRHeader *vbr, IMediaSource *source, gint64 start, gint64 *result);
104 class Mp3Demuxer : public IMediaDemuxer {
105 private:
106 Mp3FrameReader *reader;
107 bool xing;
109 MediaResult ReadHeader ();
111 static MediaResult GetFrameCallback (MediaClosure *closure);
113 protected:
114 virtual ~Mp3Demuxer ();
116 virtual void GetFrameAsyncInternal (IMediaStream *stream);
117 virtual void OpenDemuxerAsyncInternal ();
118 virtual void SeekAsyncInternal (guint64 timeToSeek);
119 virtual void SwitchMediaStreamAsyncInternal (IMediaStream *stream) {}; // An mp3 file has only 1 stream, so this doesn't make any sense
121 public:
122 Mp3Demuxer (Media *media, IMediaSource *source);
124 virtual const char *GetName () { return "Mp3Demuxer"; }
127 class Mp3DemuxerInfo : public DemuxerInfo {
128 public:
129 virtual MediaResult Supports (IMediaSource *source);
130 virtual IMediaDemuxer *Create (Media *media, IMediaSource *source);
131 virtual const char *GetName () { return "Mp3Demuxer"; }
134 bool mpeg_parse_header (MpegFrameHeader *mpeg, const guint8 *buffer);
135 double mpeg_frame_length (MpegFrameHeader *mpeg, bool xing);
137 #endif