| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <iostream> | 5 #include <iostream> |
| 6 #include <signal.h> | 6 #include <signal.h> |
| 7 #include <X11/keysym.h> | 7 #include <X11/keysym.h> |
| 8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
| 9 | 9 |
| 10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/file_path.h" | 12 #include "base/file_path.h" |
| 13 #include "base/scoped_ptr.h" | 13 #include "base/scoped_ptr.h" |
| 14 #include "base/thread.h" | 14 #include "base/thread.h" |
| 15 #include "base/waitable_event.h" | 15 #include "media/base/callback.h" |
| 16 #include "media/base/media.h" | 16 #include "media/base/media.h" |
| 17 #include "media/base/media_switches.h" | 17 #include "media/base/media_switches.h" |
| 18 #include "media/base/pipeline_impl.h" | 18 #include "media/base/pipeline_impl.h" |
| 19 #include "media/filters/audio_renderer_impl.h" | 19 #include "media/filters/audio_renderer_impl.h" |
| 20 #include "media/filters/ffmpeg_audio_decoder.h" | 20 #include "media/filters/ffmpeg_audio_decoder.h" |
| 21 #include "media/filters/ffmpeg_demuxer.h" | 21 #include "media/filters/ffmpeg_demuxer.h" |
| 22 #include "media/filters/ffmpeg_video_decoder.h" | 22 #include "media/filters/ffmpeg_video_decoder.h" |
| 23 #include "media/filters/file_data_source.h" | 23 #include "media/filters/file_data_source.h" |
| 24 #include "media/filters/null_audio_renderer.h" | 24 #include "media/filters/null_audio_renderer.h" |
| 25 #include "media/filters/omx_video_decoder.h" | 25 #include "media/filters/omx_video_decoder.h" |
| 26 | 26 |
| 27 #if defined(RENDERER_GL) | 27 #if defined(RENDERER_GL) |
| 28 #include "media/tools/player_x11/gl_video_renderer.h" | 28 #include "media/tools/player_x11/gl_video_renderer.h" |
| 29 typedef GlVideoRenderer Renderer; | 29 typedef GlVideoRenderer Renderer; |
| 30 #elif defined(RENDERER_GLES) | 30 #elif defined(RENDERER_GLES) |
| 31 #include "media/tools/player_x11/gles_video_renderer.h" | 31 #include "media/tools/player_x11/gles_video_renderer.h" |
| 32 typedef GlesVideoRenderer Renderer; | 32 typedef GlesVideoRenderer Renderer; |
| 33 #elif defined(RENDERER_X11) | 33 #elif defined(RENDERER_X11) |
| 34 #include "media/tools/player_x11/x11_video_renderer.h" | 34 #include "media/tools/player_x11/x11_video_renderer.h" |
| 35 typedef X11VideoRenderer Renderer; | 35 typedef X11VideoRenderer Renderer; |
| 36 #else | 36 #else |
| 37 #error No video renderer defined. | 37 #error No video renderer defined. |
| 38 #endif | 38 #endif |
| 39 | 39 |
| 40 Display* g_display = NULL; | 40 Display* g_display = NULL; |
| 41 Window g_window = 0; | 41 Window g_window = 0; |
| 42 bool g_running = false; | 42 bool g_running = false; |
| 43 | 43 |
| 44 void Quit(MessageLoop* message_loop) { |
| 45 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 46 } |
| 47 |
| 44 // Initialize X11. Returns true if successful. This method creates the X11 | 48 // Initialize X11. Returns true if successful. This method creates the X11 |
| 45 // window. Further initialization is done in X11VideoRenderer. | 49 // window. Further initialization is done in X11VideoRenderer. |
| 46 bool InitX11() { | 50 bool InitX11() { |
| 47 g_display = XOpenDisplay(NULL); | 51 g_display = XOpenDisplay(NULL); |
| 48 if (!g_display) { | 52 if (!g_display) { |
| 49 std::cout << "Error - cannot open display" << std::endl; | 53 std::cout << "Error - cannot open display" << std::endl; |
| 50 return false; | 54 return false; |
| 51 } | 55 } |
| 52 | 56 |
| 53 // Get properties of the screen. | 57 // Get properties of the screen. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 return true; | 128 return true; |
| 125 } | 129 } |
| 126 | 130 |
| 127 void TerminateHandler(int signal) { | 131 void TerminateHandler(int signal) { |
| 128 g_running = false; | 132 g_running = false; |
| 129 } | 133 } |
| 130 | 134 |
| 131 void PeriodicalUpdate( | 135 void PeriodicalUpdate( |
| 132 media::PipelineImpl* pipeline, | 136 media::PipelineImpl* pipeline, |
| 133 MessageLoop* message_loop, | 137 MessageLoop* message_loop, |
| 134 base::WaitableEvent* stop_event, | |
| 135 bool audio_only) { | 138 bool audio_only) { |
| 136 if (!g_running) { | 139 if (!g_running) { |
| 137 message_loop->Quit(); | 140 message_loop->Quit(); |
| 138 return; | 141 return; |
| 139 } | 142 } |
| 140 | 143 |
| 141 // Consume all the X events | 144 // Consume all the X events |
| 142 while (XPending(g_display)) { | 145 while (XPending(g_display)) { |
| 143 XEvent e; | 146 XEvent e; |
| 144 XNextEvent(g_display, &e); | 147 XNextEvent(g_display, &e); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 166 &depth); | 169 &depth); |
| 167 base::TimeDelta time = pipeline->GetMediaDuration(); | 170 base::TimeDelta time = pipeline->GetMediaDuration(); |
| 168 pipeline->Seek(time*e.xbutton.x/width, NULL); | 171 pipeline->Seek(time*e.xbutton.x/width, NULL); |
| 169 } | 172 } |
| 170 break; | 173 break; |
| 171 case KeyPress: | 174 case KeyPress: |
| 172 { | 175 { |
| 173 KeySym key = XKeycodeToKeysym(g_display, e.xkey.keycode, 0); | 176 KeySym key = XKeycodeToKeysym(g_display, e.xkey.keycode, 0); |
| 174 if (key == XK_Escape) { | 177 if (key == XK_Escape) { |
| 175 g_running = false; | 178 g_running = false; |
| 176 // QuitNow is more responsive than Quit since renderer_base is till | 179 // Quit message_loop only when pipeline is fully stopped. |
| 177 // posting paint messages. | 180 pipeline->Stop(media::TaskToCallbackAdapter::NewCallback( |
| 178 pipeline->Stop(NewCallback(stop_event, | 181 NewRunnableFunction(Quit, message_loop))); |
| 179 &base::WaitableEvent::Signal)); | |
| 180 message_loop->Quit(); | |
| 181 return; | 182 return; |
| 182 } else if (key == XK_space) { | 183 } else if (key == XK_space) { |
| 183 if (pipeline->GetPlaybackRate() < 0.01f) // paused | 184 if (pipeline->GetPlaybackRate() < 0.01f) // paused |
| 184 pipeline->SetPlaybackRate(1.0f); | 185 pipeline->SetPlaybackRate(1.0f); |
| 185 else | 186 else |
| 186 pipeline->SetPlaybackRate(0.0f); | 187 pipeline->SetPlaybackRate(0.0f); |
| 187 } | 188 } |
| 188 } | 189 } |
| 189 break; | 190 break; |
| 190 default: | 191 default: |
| 191 break; | 192 break; |
| 192 } | 193 } |
| 193 } | 194 } |
| 194 | 195 |
| 195 message_loop->PostDelayedTask(FROM_HERE, | 196 message_loop->PostDelayedTask(FROM_HERE, |
| 196 NewRunnableFunction(PeriodicalUpdate, pipeline, | 197 NewRunnableFunction(PeriodicalUpdate, pipeline, |
| 197 message_loop, stop_event, audio_only), 10); | 198 message_loop, audio_only), 10); |
| 198 } | 199 } |
| 199 | 200 |
| 200 int main(int argc, char** argv) { | 201 int main(int argc, char** argv) { |
| 201 // Read arguments. | 202 // Read arguments. |
| 202 if (argc == 1) { | 203 if (argc == 1) { |
| 203 std::cout << "Usage: " << argv[0] << " --file=FILE" << std::endl | 204 std::cout << "Usage: " << argv[0] << " --file=FILE" << std::endl |
| 204 << std::endl | 205 << std::endl |
| 205 << "Optional arguments:" << std::endl | 206 << "Optional arguments:" << std::endl |
| 206 << " [--enable-openmax]" | 207 << " [--enable-openmax]" |
| 207 << " [--audio]" | 208 << " [--audio]" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 225 | 226 |
| 226 // Initialize X11. | 227 // Initialize X11. |
| 227 if (!InitX11()) | 228 if (!InitX11()) |
| 228 return 1; | 229 return 1; |
| 229 | 230 |
| 230 // Initialize the pipeline thread and the pipeline. | 231 // Initialize the pipeline thread and the pipeline. |
| 231 base::AtExitManager at_exit; | 232 base::AtExitManager at_exit; |
| 232 scoped_ptr<base::Thread> thread; | 233 scoped_ptr<base::Thread> thread; |
| 233 scoped_refptr<media::PipelineImpl> pipeline; | 234 scoped_refptr<media::PipelineImpl> pipeline; |
| 234 MessageLoop message_loop; | 235 MessageLoop message_loop; |
| 235 base::WaitableEvent stop_event(false, false); | |
| 236 thread.reset(new base::Thread("PipelineThread")); | 236 thread.reset(new base::Thread("PipelineThread")); |
| 237 thread->Start(); | 237 thread->Start(); |
| 238 if (InitPipeline(thread->message_loop(), filename.c_str(), | 238 if (InitPipeline(thread->message_loop(), filename.c_str(), |
| 239 enable_audio, &pipeline, &message_loop)) { | 239 enable_audio, &pipeline, &message_loop)) { |
| 240 // Main loop of the application. | 240 // Main loop of the application. |
| 241 g_running = true; | 241 g_running = true; |
| 242 | 242 |
| 243 // Check if video is present. | 243 // Check if video is present. |
| 244 audio_only = !pipeline->IsRendered(media::mime_type::kMajorTypeVideo); | 244 audio_only = !pipeline->IsRendered(media::mime_type::kMajorTypeVideo); |
| 245 | 245 |
| 246 message_loop.PostTask(FROM_HERE, | 246 message_loop.PostTask(FROM_HERE, |
| 247 NewRunnableFunction(PeriodicalUpdate, pipeline.get(), | 247 NewRunnableFunction(PeriodicalUpdate, pipeline.get(), |
| 248 &message_loop, &stop_event, audio_only)); | 248 &message_loop, audio_only)); |
| 249 message_loop.Run(); | 249 message_loop.Run(); |
| 250 | |
| 251 // Need to wait for pipeline to be fully stopped before stopping the thread. | |
| 252 stop_event.Wait(); | |
| 253 } else{ | 250 } else{ |
| 254 std::cout << "Pipeline initialization failed..." << std::endl; | 251 std::cout << "Pipeline initialization failed..." << std::endl; |
| 255 } | 252 } |
| 256 | 253 |
| 257 // Cleanup tasks. | 254 // Cleanup tasks. |
| 258 thread->Stop(); | 255 thread->Stop(); |
| 259 XDestroyWindow(g_display, g_window); | 256 XDestroyWindow(g_display, g_window); |
| 260 XCloseDisplay(g_display); | 257 XCloseDisplay(g_display); |
| 261 return 0; | 258 return 0; |
| 262 } | 259 } |
| OLD | NEW |