Mercurial > hg > forks > bilotrip-mj12
annotate liboggplayer-src/src/play.cpp @ 14:083c73ceb716
Get rid of the vorbis related code.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 05 Aug 2013 16:54:46 +0300 |
parents | 105513a2e3c9 |
children | 3eacedd172ab |
rev | line source |
---|---|
2 | 1 #include "imp.hpp" |
2 | |
3 bool OggPlayer::Imp::ready() { | |
4 return audio_cache_ready; | |
5 } | |
6 // return true if need more data | |
7 // the return value is strange but the function is | |
8 // for internal use only and should only be called | |
9 // in play() | |
10 bool OggPlayer::Imp::decode_audio() { | |
14
083c73ceb716
Get rid of the vorbis related code.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
11 #ifdef VORBIS_SUPPORT |
2 | 12 int ret; |
13 float **pcm; | |
14 // if there's pending, decoded audio, grab it | |
15 while ((ret = vorbis_synthesis_pcmout(&v_state, &pcm)) > 0) { | |
16 boost::unique_lock<boost::mutex> lock(audio_mut); | |
17 // first we need to convert from float to signed short | |
18 // then we will use SDL_ConvertAudio | |
19 // is our temp buffer big enough? | |
20 if (cirbuf.capacity() < ret * v_info.channels * cvt.len_mult | |
21 * sizeof(short)) { | |
22 cirbuf.set_capacity(ret * v_info.channels * cvt.len_mult * 16 | |
23 * sizeof(short)); | |
24 } | |
25 if (cirbuf.capacity() - cirbuf.size() < ret * v_info.channels | |
26 * cvt.len_mult * sizeof(short)) { | |
27 audio_cache_ready = true; | |
28 return false; | |
29 } | |
30 if ((audio_buffer_size) < ret * v_info.channels * cvt.len_mult | |
31 * sizeof(short)) { | |
32 if (audio_buffer) | |
33 delete[] audio_buffer; | |
34 audio_buffer_size = ret * v_info.channels * cvt.len_mult | |
35 * sizeof(short); | |
36 audio_buffer = new char[audio_buffer_size]; | |
37 } | |
38 // convert from float to short | |
39 int k = 0; | |
40 char* char_ab = (char*) audio_buffer; | |
41 short* short_ab = (short*) audio_buffer; | |
42 for (int i = 0; i < ret; i++) { | |
43 for (int j = 0; j < v_info.channels; j++) { | |
44 int val = (int)(pcm[j][i] * 32767.f); | |
45 if (val > 32767) | |
46 val = 32767; | |
47 if (val < -32768) | |
48 val = -32768; | |
49 short_ab[k++] = val; | |
50 | |
51 } | |
52 } | |
53 vorbis_synthesis_read(&v_state, ret); | |
54 // now we can use SDL_ConvertAudio | |
55 cvt.len = k * sizeof(short); | |
56 cvt.buf = (Uint8*) char_ab; | |
57 SDL_ConvertAudio(&cvt); | |
58 | |
59 for (int i = 0; i < cvt.len_cvt; i++) { | |
60 cirbuf.push_back(char_ab[i]); | |
61 } | |
62 | |
63 | |
64 if(v_state.granulepos!=0){ | |
65 AudioGranulePos agp; | |
66 agp.pos = audio_bytes_played+cvt.len_cvt; | |
67 agp.set_time = (double)v_state.granulepos/(double)v_info.rate; | |
68 audio_granule_poses.push_back(agp); | |
69 } | |
70 | |
71 lock.unlock(); | |
72 audio_ready_cond.notify_one(); | |
73 return false; | |
74 | |
75 } | |
76 // no pending audio; is there a pending packet to decode? | |
77 if (ogg_stream_packetout(&o_vsstate, &o_packet) > 0) { | |
78 if (vorbis_synthesis(&v_block, &o_packet) == 0) { | |
79 vorbis_synthesis_blockin(&v_state, &v_block); | |
80 return false; | |
81 } | |
82 } else { return true; } | |
14
083c73ceb716
Get rid of the vorbis related code.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
83 #endif |
083c73ceb716
Get rid of the vorbis related code.
Matti Hamalainen <ccr@tnsp.org>
parents:
2
diff
changeset
|
84 return true; |
2 | 85 } |
86 // similar to decode_audio | |
87 bool OggPlayer::Imp::decode_video() { | |
88 bool was_ready=videobuf_ready; | |
89 boost::unique_lock<boost::mutex> lock(video_mut, boost::defer_lock); | |
90 ogg_int64_t videobuf_granulepos = -1; | |
91 if (!videobuf_ready){ | |
92 if(!lock.try_lock()) | |
93 return false; | |
94 } | |
95 while (!videobuf_ready) { | |
96 // theora is one in, one out... | |
97 if (ogg_stream_packetout(&o_tsstate, &o_packet) > 0) { | |
98 | |
99 if(pp_inc){ | |
100 pp_level+=pp_inc; | |
101 theora_control(&t_state,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level)); | |
102 pp_inc=0; | |
103 } | |
104 if (o_packet.granulepos >= 0) { | |
105 theora_control(&t_state, TH_DECCTL_SET_GRANPOS, | |
106 &o_packet.granulepos, sizeof(o_packet.granulepos)); | |
107 } | |
108 if (theora_decode_packetin(&t_state, &o_packet) == 0) { | |
109 videobuf_granulepos = t_state.granulepos; | |
110 videobuf_time = theora_granule_time(&t_state, videobuf_granulepos); | |
111 | |
112 if (videobuf_time >= get_time()){ | |
113 videobuf_ready = true; | |
114 frame++; | |
115 } | |
116 else { | |
117 // If we are too slow, reduce the pp level. | |
118 pp_inc=pp_level>0?-1:0; | |
119 } | |
120 } | |
121 | |
122 } else | |
123 break; | |
124 } | |
125 lock.unlock(); | |
126 if(videobuf_ready!=was_ready) | |
127 video_ready_cond.notify_one(); | |
128 | |
129 return !videobuf_ready; | |
130 } | |
131 | |
132 void OggPlayer::Imp::play_loop() { | |
133 if(!file_in.is_open()) return; | |
134 audio_cache_ready = false; | |
135 audio_bytes_played = 0; | |
136 bool audio_need_data = vorbis_p; | |
137 bool video_need_data = theora_p; | |
138 timer.restart(); | |
139 // buffer_data() will close the file on eof | |
140 while ((file_in.is_open() || !audio_need_data || !video_need_data) && playing) { | |
141 | |
142 // sync audio video timer | |
143 while(!audio_granule_poses.empty() && | |
144 audio_granule_poses.front().pos <= audio_bytes_played){ | |
145 time_factor= audio_granule_poses.front().set_time/timer.elapsed(); | |
146 audio_granule_poses.pop_front(); | |
147 } | |
148 | |
149 if (theora_p && !videobuf_ready) { | |
150 video_need_data = decode_video(); | |
151 } | |
152 | |
153 if (vorbis_p) { | |
154 audio_need_data = decode_audio(); | |
155 } | |
156 | |
157 // are we at or past time for this video frame? | |
158 if (videobuf_ready && videobuf_time <= get_time()) { | |
159 videobuf_ready = false; | |
160 } | |
161 // if no data yet for somebody, grab another page | |
162 if (file_in.is_open() && (audio_need_data || video_need_data)) { | |
163 // buffer_data() can handle eof itself | |
164 buffer_data(); | |
165 while (ogg_sync_pageout(&o_sync, &o_page) > 0) { | |
166 queue_page(&o_page); | |
167 } | |
168 audio_need_data = false; | |
169 video_need_data = false; | |
170 } | |
171 } | |
172 playing = false; | |
173 | |
174 // do not risk a lock | |
175 audio_ready_cond.notify_one(); | |
176 video_ready_cond.notify_one(); | |
177 | |
178 // cleanup | |
179 close(); | |
180 } | |
181 | |
182 void OggPlayer::Imp::play() { | |
183 playing = true; | |
184 play_thread = boost::thread(boost::bind(&OggPlayer::Imp::play_loop, this)); | |
185 } | |
186 |