2
|
1 #include <oggplayer.h>
|
|
2 #include "imp.hpp"
|
|
3
|
|
4 OggPlayer::~OggPlayer() {
|
|
5 imp->refs--;
|
|
6 if(imp->refs==0){
|
|
7 close();
|
|
8 delete imp;
|
|
9 }
|
|
10 }
|
|
11
|
|
12 OggPlayer::OggPlayer() {
|
|
13 imp = new Imp;
|
|
14 }
|
|
15
|
|
16 OggPlayer::OggPlayer(OggPlayer& os) {
|
|
17 imp = os.imp;
|
|
18 imp->refs++;
|
|
19 }
|
|
20
|
|
21 OggPlayer& OggPlayer::operator =(OggPlayer& os){
|
|
22 if(this==&os) return *this;
|
|
23 imp->refs--;
|
|
24 if(imp->refs==0){
|
|
25 close();
|
|
26 delete imp;
|
|
27 }
|
|
28 imp = os.imp;
|
|
29 imp->refs++;
|
|
30 return *this;
|
|
31 }
|
|
32
|
|
33 OggPlayer::OggPlayer(std::string path, AudioFormat audio_format, int channels,
|
|
34 int rate, VideoFormat video_format){
|
|
35 imp = new Imp;
|
|
36 open(path, audio_format, channels, rate, video_format);
|
|
37 }
|
|
38
|
|
39 void OggPlayer::open(std::string path, AudioFormat audio_format, int channels,
|
|
40 int rate, VideoFormat video_format) {
|
|
41 if(playing()) close();
|
|
42 imp->open(path, audio_format, channels, rate, video_format);
|
|
43 }
|
|
44
|
|
45 void OggPlayer::close() {
|
|
46 imp->playing = false;
|
|
47 // wait for play thread to terminate (if any)
|
|
48 imp->play_thread.join();
|
|
49 }
|
|
50
|
|
51 bool OggPlayer::fail() {
|
|
52 return imp->failbit;
|
|
53 }
|
|
54
|
|
55 void OggPlayer::play() {
|
|
56 imp->play();
|
|
57 }
|
|
58
|
|
59 bool OggPlayer::playing() {
|
|
60 return imp->playing;
|
|
61 }
|
|
62
|
|
63
|
|
64 int OggPlayer::audio_read(char* buf, unsigned int size) {
|
|
65 if(NULL==buf || !imp->vorbis_p || !playing() || !imp->ready()) return 0;
|
|
66 boost::unique_lock<boost::mutex> lock(imp->audio_mut);
|
|
67
|
|
68 while ((imp->cirbuf.size() < size) && playing()) {
|
|
69 if(imp->cirbuf.capacity()< size)
|
|
70 {
|
|
71 imp->cirbuf.set_capacity(2*size);
|
|
72 }
|
|
73 imp->audio_ready_cond.wait(lock);
|
|
74 }
|
|
75
|
|
76 unsigned int k = 0;
|
|
77 while (k < size && !imp->cirbuf.empty()) {
|
|
78 buf[k++] = imp->cirbuf.front();
|
|
79 imp->cirbuf.pop_front();
|
|
80 }
|
|
81 imp->audio_bytes_played+=k;
|
|
82
|
|
83 return k;
|
|
84 }
|
|
85
|
|
86 bool OggPlayer::yuv_buffer_try_lock(YUVBuffer *buffer) {
|
|
87 if (!playing() || !imp->theora_p || !imp->ready())
|
|
88 return false;
|
|
89 // no new data, no reason to lock
|
|
90 if(imp->last_frame_read==imp->frame)
|
|
91 return false;
|
|
92 imp->video_lock.lock();
|
|
93 while (!imp->videobuf_ready && playing()) {
|
|
94 imp->video_ready_cond.wait(imp->video_lock);
|
|
95 }
|
|
96 //ready and locked!
|
|
97 yuv_buffer yuv;
|
|
98 theora_decode_YUVout(&(imp->t_state), &yuv);
|
|
99
|
|
100 buffer->y_width = yuv.y_width;
|
|
101 buffer->y_height = yuv.y_height;
|
|
102 buffer->y_stride = yuv.y_stride;
|
|
103 buffer->uv_width = yuv.uv_width;
|
|
104 buffer->uv_height = yuv.uv_height;
|
|
105 buffer->uv_stride = yuv.uv_stride;
|
|
106 buffer->y = yuv.y;
|
|
107 buffer->u = yuv.u;
|
|
108 buffer->v = yuv.v;
|
|
109
|
|
110 imp->last_frame_read = imp->frame;
|
|
111 return true;
|
|
112 }
|
|
113
|
|
114 void OggPlayer::yuv_buffer_unlock() {
|
|
115 imp->video_lock.unlock();
|
|
116 }
|
|
117
|
|
118 inline int clamp(int val){
|
|
119 if(val<0) return 0;
|
|
120 if(val>255) return 255;
|
|
121 return val;
|
|
122 }
|
|
123
|
|
124 bool OggPlayer::video_read(char* buf, int stride) {
|
|
125 YUVBuffer yuv;
|
|
126 if(NULL==buf) return false;
|
|
127 if (!yuv_buffer_try_lock(&yuv))
|
|
128 return false;
|
|
129
|
|
130 if(0==stride) stride=width()*imp->pixel_format.bpp;
|
|
131 int h = height(), w = width();
|
|
132
|
|
133 int uv_ki=yuv.y_width/yuv.uv_width;
|
|
134 int uv_kj=yuv.y_height/yuv.uv_height;
|
|
135
|
|
136 int y_offset = offset_x() + yuv.y_stride * offset_y();
|
|
137 int uv_offset = offset_x()/uv_ki+yuv.uv_stride * offset_y()/uv_kj;
|
|
138 int y_p,uv_p,b_p;
|
|
139
|
|
140 for(int j=0;j<h;j++){
|
|
141 y_p=y_offset+j*yuv.y_stride;
|
|
142 b_p=j*stride;
|
|
143 uv_p=uv_offset+j/uv_kj*yuv.uv_stride;
|
|
144
|
|
145 for(int i=0;i<w;i++){
|
|
146 //http://en.wikipedia.org/wiki/YUV
|
|
147 int y = yuv.y[y_p]-16;
|
|
148 int u = yuv.u[uv_p]-128;
|
|
149 int v = yuv.v[uv_p]-128;
|
|
150 int r =clamp((y*298+409*v+128)>>8);
|
|
151 int g =clamp((y*298-100*v-208*u+128)>>8);
|
|
152 int b =clamp((y*298+516*u+128)>>8);
|
|
153 buf[b_p+imp->pixel_format.r_offset]=r;
|
|
154 buf[b_p+imp->pixel_format.g_offset]=g;
|
|
155 buf[b_p+imp->pixel_format.b_offset]=b;
|
|
156 if(4==imp->pixel_format.bpp)
|
|
157 buf[b_p+3]=255;
|
|
158
|
|
159 b_p+=imp->pixel_format.bpp;
|
|
160 y_p++;
|
|
161 if( i%uv_ki == uv_ki-1 ) uv_p++;
|
|
162 }
|
|
163 }
|
|
164 yuv_buffer_unlock();
|
|
165 return true;
|
|
166 }
|
|
167
|
|
168 int OggPlayer::width() {
|
|
169 return imp->t_info.width;
|
|
170 }
|
|
171 int OggPlayer::height() {
|
|
172 return imp->t_info.height;
|
|
173 }
|
|
174 int OggPlayer::offset_x() {
|
|
175 return imp->t_info.offset_x;
|
|
176 }
|
|
177 int OggPlayer::offset_y() {
|
|
178 return imp->t_info.offset_y;
|
|
179 }
|
|
180
|