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 bool OggPlayer::yuv_buffer_try_lock(YUVBuffer *buffer) {
|
|
64 if (!playing() || !imp->theora_p || !imp->ready())
|
|
65 return false;
|
|
66 // no new data, no reason to lock
|
|
67 if(imp->last_frame_read==imp->frame)
|
|
68 return false;
|
|
69 imp->video_lock.lock();
|
|
70 while (!imp->videobuf_ready && playing()) {
|
|
71 imp->video_ready_cond.wait(imp->video_lock);
|
|
72 }
|
|
73 //ready and locked!
|
|
74 yuv_buffer yuv;
|
|
75 theora_decode_YUVout(&(imp->t_state), &yuv);
|
|
76
|
|
77 buffer->y_width = yuv.y_width;
|
|
78 buffer->y_height = yuv.y_height;
|
|
79 buffer->y_stride = yuv.y_stride;
|
|
80 buffer->uv_width = yuv.uv_width;
|
|
81 buffer->uv_height = yuv.uv_height;
|
|
82 buffer->uv_stride = yuv.uv_stride;
|
|
83 buffer->y = yuv.y;
|
|
84 buffer->u = yuv.u;
|
|
85 buffer->v = yuv.v;
|
|
86
|
|
87 imp->last_frame_read = imp->frame;
|
|
88 return true;
|
|
89 }
|
|
90
|
|
91 void OggPlayer::yuv_buffer_unlock() {
|
|
92 imp->video_lock.unlock();
|
|
93 }
|
|
94
|
|
95 inline int clamp(int val){
|
|
96 if(val<0) return 0;
|
|
97 if(val>255) return 255;
|
|
98 return val;
|
|
99 }
|
|
100
|
|
101 bool OggPlayer::video_read(char* buf, int stride) {
|
|
102 YUVBuffer yuv;
|
|
103 if(NULL==buf) return false;
|
|
104 if (!yuv_buffer_try_lock(&yuv))
|
|
105 return false;
|
|
106
|
|
107 if(0==stride) stride=width()*imp->pixel_format.bpp;
|
|
108 int h = height(), w = width();
|
|
109
|
|
110 int uv_ki=yuv.y_width/yuv.uv_width;
|
|
111 int uv_kj=yuv.y_height/yuv.uv_height;
|
|
112
|
|
113 int y_offset = offset_x() + yuv.y_stride * offset_y();
|
|
114 int uv_offset = offset_x()/uv_ki+yuv.uv_stride * offset_y()/uv_kj;
|
|
115 int y_p,uv_p,b_p;
|
|
116
|
|
117 for(int j=0;j<h;j++){
|
|
118 y_p=y_offset+j*yuv.y_stride;
|
|
119 b_p=j*stride;
|
|
120 uv_p=uv_offset+j/uv_kj*yuv.uv_stride;
|
|
121
|
|
122 for(int i=0;i<w;i++){
|
|
123 //http://en.wikipedia.org/wiki/YUV
|
|
124 int y = yuv.y[y_p]-16;
|
|
125 int u = yuv.u[uv_p]-128;
|
|
126 int v = yuv.v[uv_p]-128;
|
|
127 int r =clamp((y*298+409*v+128)>>8);
|
|
128 int g =clamp((y*298-100*v-208*u+128)>>8);
|
|
129 int b =clamp((y*298+516*u+128)>>8);
|
|
130 buf[b_p+imp->pixel_format.r_offset]=r;
|
|
131 buf[b_p+imp->pixel_format.g_offset]=g;
|
|
132 buf[b_p+imp->pixel_format.b_offset]=b;
|
|
133 if(4==imp->pixel_format.bpp)
|
|
134 buf[b_p+3]=255;
|
|
135
|
|
136 b_p+=imp->pixel_format.bpp;
|
|
137 y_p++;
|
|
138 if( i%uv_ki == uv_ki-1 ) uv_p++;
|
|
139 }
|
|
140 }
|
|
141 yuv_buffer_unlock();
|
|
142 return true;
|
|
143 }
|
|
144
|
|
145 int OggPlayer::width() {
|
|
146 return imp->t_info.width;
|
|
147 }
|
|
148 int OggPlayer::height() {
|
|
149 return imp->t_info.height;
|
|
150 }
|
|
151 int OggPlayer::offset_x() {
|
|
152 return imp->t_info.offset_x;
|
|
153 }
|
|
154 int OggPlayer::offset_y() {
|
|
155 return imp->t_info.offset_y;
|
|
156 }
|
|
157
|