15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream> // NOLINT 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_vector.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/null_audio_sink.h" 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "media/base/audio_hardware_config.h" 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/bind_to_current_loop.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/decryptor.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_log.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_switches.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/pipeline.h" 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/base/text_track.h" 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/base/text_track_config.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/audio_renderer_impl.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/ffmpeg_audio_decoder.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/ffmpeg_demuxer.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/ffmpeg_video_decoder.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/file_data_source.h" 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/filters/renderer_impl.h" 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/filters/video_renderer_impl.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/tools/player_x11/data_source_logger.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Include X11 headers here because X11/Xlib.h #define's Status 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which causes compiler errors with Status enum declarations 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in media::DemuxerStream & media::AudioDecoder. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/XKBlib.h> 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h> 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/tools/player_x11/gl_video_renderer.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/tools/player_x11/x11_video_renderer.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Display* g_display = NULL; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Window g_window = 0; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool g_running = false; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)media::AudioManager* g_audio_manager = NULL; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<media::DataSource> CreateDataSource(const std::string& file_path) { 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::FileDataSource* file_data_source = new media::FileDataSource(); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(file_data_source->Initialize(base::FilePath(file_path))); 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<media::DataSource> data_source(file_data_source); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return data_source.Pass(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initialize X11. Returns true if successful. This method creates the X11 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// window. Further initialization is done in X11VideoRenderer. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InitX11() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_display = XOpenDisplay(NULL); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_display) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cout << "Error - cannot open display" << std::endl; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get properties of the screen. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int screen = DefaultScreen(g_display); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int root_window = RootWindow(g_display, screen); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates the window. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_window = XCreateSimpleWindow(g_display, root_window, 1, 1, 100, 50, 0, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BlackPixel(g_display, screen), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BlackPixel(g_display, screen)); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XStoreName(g_display, g_window, "X11 Media Player"); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSelectInput(g_display, g_window, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExposureMask | ButtonPressMask | KeyPressMask); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XMapWindow(g_display, g_window); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void DoNothing() {} 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void OnStatus(media::PipelineStatus status) {} 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstatic void OnMetadata(media::PipelineMetadata metadata) {} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic void OnBufferingStateChanged(media::BufferingState buffering_state) {} 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic void OnAddTextTrack(const media::TextTrackConfig& config, 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const media::AddTextTrackDoneCB& done_cb) { 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static void NeedKey(const std::string& type, 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::vector<uint8>& init_data) { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::cout << "File is encrypted." << std::endl; 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void SaveStatusAndSignal(base::WaitableEvent* event, 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::PipelineStatus* status_out, 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::PipelineStatus status) { 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *status_out = status; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event->Signal(); 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(vrk): Re-enabled audio. (crbug.com/112159) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void InitPipeline( 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::Pipeline* pipeline, 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) media::Demuxer* demuxer, 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const media::VideoRendererImpl::PaintCB& paint_cb, 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bool /* enable_audio */) { 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedVector<media::VideoDecoder> video_decoders; 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) video_decoders.push_back(new media::FFmpegVideoDecoder(task_runner)); 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<media::VideoRenderer> video_renderer( 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new media::VideoRendererImpl(task_runner, 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci video_decoders.Pass(), 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci media::SetDecryptorReadyCB(), 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci paint_cb, 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true, 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new media::MediaLog())); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedVector<media::AudioDecoder> audio_decoders; 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) audio_decoders.push_back(new media::FFmpegAudioDecoder(task_runner, 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) media::LogCB())); 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::AudioParameters out_params( 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::CHANNEL_LAYOUT_STEREO, 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 44100, 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 16, 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 512); 136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::AudioHardwareConfig hardware_config(out_params, out_params); 137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<media::AudioRenderer> audio_renderer( 139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new media::AudioRendererImpl(task_runner, 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new media::NullAudioSink(task_runner), 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch audio_decoders.Pass(), 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch media::SetDecryptorReadyCB(), 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci hardware_config, 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new media::MediaLog())); 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<media::Renderer> renderer(new media::RendererImpl( 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner, demuxer, audio_renderer.Pass(), video_renderer.Pass())); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WaitableEvent event(true, false); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media::PipelineStatus status; 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pipeline->Start(demuxer, 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci renderer.Pass(), 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&DoNothing), 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&OnStatus), 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&SaveStatusAndSignal, &event, &status), 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&OnMetadata), 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&OnBufferingStateChanged), 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&DoNothing), 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&OnAddTextTrack)); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait until the pipeline is fully initialized. 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.Wait(); 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHECK_EQ(status, media::PIPELINE_OK) << "Pipeline initialization failed"; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // And start the playback. 167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) pipeline->SetPlaybackRate(1.0f); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TerminateHandler(int signal) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_running = false; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PeriodicalUpdate( 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::Pipeline* pipeline, 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::MessageLoop* message_loop) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_running) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // interrupt signal was received during last time period. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Quit message_loop only when pipeline is fully stopped. 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pipeline->Stop(base::MessageLoop::QuitClosure()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Consume all the X events 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (XPending(g_display)) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XEvent e; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XNextEvent(g_display, &e); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (e.type) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ButtonPress: 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window window; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, y; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int width, height, border_width, depth; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetGeometry(g_display, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_window, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &window, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &x, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &y, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &width, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &height, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &border_width, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &depth); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta time = pipeline->GetMediaDuration(); 204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch pipeline->Seek(time*e.xbutton.x/width, base::Bind(&OnStatus)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case KeyPress: 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KeySym key = XkbKeycodeToKeysym(g_display, e.xkey.keycode, 0, 0); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == XK_Escape) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_running = false; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Quit message_loop only when pipeline is fully stopped. 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pipeline->Stop(base::MessageLoop::QuitClosure()); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (key == XK_space) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipeline->GetPlaybackRate() < 0.01f) // paused 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipeline->SetPlaybackRate(1.0f); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipeline->SetPlaybackRate(0.0f); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop->PostDelayedTask( 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&PeriodicalUpdate, 231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::Unretained(pipeline), 232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch message_loop), 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(10)); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AtExitManager at_exit; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media::InitializeMediaLibraryForTesting(); 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::Init(argc, argv); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine* command_line = CommandLine::ForCurrentProcess(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string filename = command_line->GetSwitchValueASCII("file"); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filename.empty()) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::cout << "Usage: " << argv[0] << " --file=FILE" << std::endl 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << std::endl 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Optional arguments:" << std::endl 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " [--audio]" 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " [--alsa-device=DEVICE]" 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " [--use-gl]" 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " [--streaming]" << std::endl 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " Press [ESC] to stop" << std::endl 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " Press [SPACE] to toggle pause/play" << std::endl 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " Press mouse left button to seek" << std::endl; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<media::AudioManager> audio_manager( 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::AudioManager::CreateForTesting()); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_audio_manager = audio_manager.get(); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch logging::LoggingSettings settings; 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch logging::InitLogging(settings); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Install the signal handler. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal(SIGTERM, &TerminateHandler); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal(SIGINT, &TerminateHandler); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize X11. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!InitX11()) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the pipeline thread and the pipeline. 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop message_loop; 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Thread media_thread("MediaThread"); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media_thread.Start(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu media::VideoRendererImpl::PaintCB paint_cb; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_line->HasSwitch("use-gl")) { 2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu paint_cb = media::BindToCurrentLoop(base::Bind( 2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu &GlVideoRenderer::Paint, new GlVideoRenderer(g_display, g_window))); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu paint_cb = media::BindToCurrentLoop(base::Bind( 2855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu &X11VideoRenderer::Paint, new X11VideoRenderer(g_display, g_window))); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<media::DataSource> data_source(new DataSourceLogger( 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateDataSource(filename), command_line->HasSwitch("streaming"))); 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<media::Demuxer> demuxer(new media::FFmpegDemuxer( 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) media_thread.message_loop_proxy(), data_source.get(), 292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&NeedKey), new media::MediaLog())); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) media::Pipeline pipeline(media_thread.message_loop_proxy(), 295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) new media::MediaLog()); 296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) InitPipeline(&pipeline, media_thread.message_loop_proxy(), demuxer.get(), 2975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu paint_cb, command_line->HasSwitch("audio")); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Main loop of the application. 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) g_running = true; 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop.PostTask(FROM_HERE, base::Bind( 303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &PeriodicalUpdate, base::Unretained(&pipeline), &message_loop)); 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) message_loop.Run(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cleanup tasks. 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media_thread.Stop(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Release callback which releases video renderer. Do this before cleaning up 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // X below since the video renderer has some X cleanup duties as well. 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint_cb.Reset(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XDestroyWindow(g_display, g_window); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XCloseDisplay(g_display); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_audio_manager = NULL; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 319