|
1
|
1 #pragma once
|
|
|
2 #include <SDK/packet_decoder.h>
|
|
|
3 /*
|
|
|
4 Helper code with common MP3 packet_decoder functionality. Primarily meant for foo_input_std-internal use.
|
|
|
5 */
|
|
|
6
|
|
|
7 class packet_decoder_mp3_common : public packet_decoder {
|
|
|
8 public:
|
|
|
9 static unsigned parseDecoderSetup( const GUID & p_owner,t_size p_param1,const void * p_param2,t_size p_param2size );
|
|
|
10
|
|
|
11 static unsigned layer_from_frame(const void *, size_t);
|
|
|
12
|
|
|
13 static unsigned get_max_frame_dependency_() {return 10;}
|
|
|
14 static double get_max_frame_dependency_time_() {return 10.0 * 1152.0 / 32000.0;}
|
|
|
15 };
|
|
|
16
|
|
|
17
|
|
|
18 template<typename impl_t>
|
|
|
19 class packet_decoder_mp3 : public packet_decoder
|
|
|
20 {
|
|
|
21 impl_t m_decoder;
|
|
|
22 unsigned m_layer;
|
|
|
23
|
|
|
24 void init(unsigned p_layer) {
|
|
|
25 m_layer = p_layer;
|
|
|
26 m_decoder.reset_after_seek();
|
|
|
27 }
|
|
|
28
|
|
|
29 bool m_MP4fixes;
|
|
|
30
|
|
|
31 public:
|
|
|
32 packet_decoder_mp3() : m_layer(0), m_MP4fixes()
|
|
|
33 {
|
|
|
34 }
|
|
|
35
|
|
|
36 ~packet_decoder_mp3()
|
|
|
37 {
|
|
|
38 }
|
|
|
39
|
|
|
40 t_size set_stream_property(const GUID & p_type, t_size p_param1, const void * p_param2, t_size p_param2size) {
|
|
|
41 return m_decoder.set_stream_property(p_type, p_param1, p_param2, p_param2size);
|
|
|
42 }
|
|
|
43
|
|
|
44 void get_info(file_info & p_info)
|
|
|
45 {
|
|
|
46 switch (m_layer)
|
|
|
47 {
|
|
|
48 case 1: p_info.info_set("codec", "MP1"); break;
|
|
|
49 case 2: p_info.info_set("codec", "MP2"); break;
|
|
|
50 case 3: p_info.info_set("codec", "MP3"); break;
|
|
|
51 default:
|
|
|
52 throw exception_io_data();
|
|
|
53 }
|
|
|
54 p_info.info_set("encoding", "lossy");
|
|
|
55 }
|
|
|
56
|
|
|
57 unsigned get_max_frame_dependency() { return 10; }
|
|
|
58 double get_max_frame_dependency_time() { return 10.0 * 1152.0 / 32000.0; }
|
|
|
59
|
|
|
60 static bool g_is_our_setup(const GUID & p_owner, t_size p_param1, const void * p_param2, t_size p_param2size) {
|
|
|
61 return packet_decoder_mp3_common::parseDecoderSetup(p_owner, p_param1, p_param2, p_param2size) != 0;
|
|
|
62 }
|
|
|
63
|
|
|
64 void open(const GUID & p_owner, bool p_decode, t_size p_param1, const void * p_param2, t_size p_param2size, abort_callback & p_abort)
|
|
|
65 {
|
|
|
66 m_MP4fixes = (p_owner == owner_MP4);
|
|
|
67 unsigned layer = packet_decoder_mp3_common::parseDecoderSetup(p_owner, p_param1, p_param2, p_param2size);
|
|
|
68 if (layer == 0) throw exception_io_data();
|
|
|
69 init(layer);
|
|
|
70 }
|
|
|
71
|
|
|
72 void reset_after_seek() {
|
|
|
73 m_decoder.reset_after_seek();
|
|
|
74 }
|
|
|
75
|
|
|
76 void decode(const void * p_buffer, t_size p_bytes, audio_chunk & p_chunk, abort_callback & p_abort) {
|
|
|
77 m_decoder.decode(p_buffer, p_bytes, p_chunk, p_abort);
|
|
|
78 }
|
|
|
79
|
|
|
80 bool analyze_first_frame_supported() { return m_MP4fixes; }
|
|
|
81 void analyze_first_frame(const void * p_buffer, t_size p_bytes, abort_callback & p_abort) {
|
|
|
82 m_layer = packet_decoder_mp3_common::layer_from_frame(p_buffer, p_bytes);
|
|
|
83 }
|
|
|
84 };
|