summaryrefslogtreecommitdiff
path: root/avmedia/source/vlc/vlcframegrabber.cxx
blob: 7a742e976e1eb5816f730ae25613188c602a8082 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <boost/bind.hpp>
#include <iostream>
#include <osl/conditn.hxx>
#include <vcl/graph.hxx>
#include <vcl/bmpacc.hxx>
#include <vcl/pngread.hxx>
#include <avmedia/mediawindow.hxx>
#include <unotools/localfilehelper.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <tools/stream.hxx>

#include "vlcframegrabber.hxx"
#include "vlcplayer.hxx"
#include "wrapper/Player.hxx"
#include "wrapper/EventManager.hxx"

using namespace ::com::sun::star;

namespace avmedia {
namespace vlc {

namespace
{
    const ::rtl::OUString AVMEDIA_VLC_GRABBER_IMPLEMENTATIONNAME = "com.sun.star.comp.avmedia.VLCFrameGrabber_VLC";
    const ::rtl::OUString AVMEDIA_VLC_GRABBER_SERVICENAME = "com.sun.star.media.VLCFrameGrabber_VLC";
    const int MSEC_IN_SEC = 1000;

    const char * const VLC_ARGS[] = {
        "-Vdummy",
        // "--ignore-config"
        "--demux",
        "ffmpeg",
        "--snapshot-format=png",
        "--ffmpeg-threads", /* Is deprecated in 2.1.0 */
        "--verbose=2",
        "--no-audio"//,
        //"--file-logging",
        //"--logfile=C:/home/dev/log/vlc_log"
    };
}

VLCFrameGrabber::VLCFrameGrabber( wrapper::EventHandler& eh, const rtl::OUString& url )
    : FrameGrabber_BASE()
    , mInstance( sizeof( VLC_ARGS ) / sizeof( VLC_ARGS[0] ), VLC_ARGS )
    , mMedia( url, mInstance )
    , mPlayer( mMedia )
    , mEventHandler( eh )
{
}

::uno::Reference< css::graphic::XGraphic > SAL_CALL VLCFrameGrabber::grabFrame( double fMediaTime )
        throw ( ::com::sun::star::uno::RuntimeException )
{
    osl::Condition condition;

    const rtl::OUString& fileName = utl::TempFile::CreateTempName();
    {
        wrapper::EventManager manager( mPlayer, mEventHandler );
        manager.onPaused(boost::bind(&osl::Condition::set, &condition));

        if ( !mPlayer.play() )
        {
            SAL_WARN("avmedia", "Couldn't play when trying to grab frame");
            return ::uno::Reference< css::graphic::XGraphic >();
        }

        mPlayer.setTime( ( fMediaTime > 0 ? fMediaTime : 0 ) * MSEC_IN_SEC );
        mPlayer.pause();

        const TimeValue timeout = {2, 0};

        //TODO: Fix this hang on Windows
#ifndef WNT
        condition.wait(&timeout);
#endif

        if ( !mPlayer.hasVout() )
        {
            SAL_WARN("avmedia", "Couldn't grab frame");
            manager.onPaused();
            return ::uno::Reference< css::graphic::XGraphic >();
        }

        mPlayer.takeSnapshot( fileName );
        mPlayer.stop();

        manager.onPaused();
    }

    rtl::OUString url;
    utl::LocalFileHelper::ConvertPhysicalNameToURL( fileName, url );
    boost::shared_ptr<SvStream> stream( utl::UcbStreamHelper::CreateStream( url,
                                                                            STREAM_STD_READ ) );

    vcl::PNGReader reader( *stream );

    const BitmapEx& bitmap = reader.Read();

    return Graphic( bitmap ).GetXGraphic();
}

::rtl::OUString SAL_CALL VLCFrameGrabber::getImplementationName() throw ( ::com::sun::star::uno::RuntimeException )
{
    return AVMEDIA_VLC_GRABBER_IMPLEMENTATIONNAME;
}

::sal_Bool SAL_CALL VLCFrameGrabber::supportsService( const ::rtl::OUString& serviceName )
        throw ( ::com::sun::star::uno::RuntimeException )
{
    return AVMEDIA_VLC_GRABBER_SERVICENAME == serviceName;
}

::uno::Sequence< ::rtl::OUString > SAL_CALL VLCFrameGrabber::getSupportedServiceNames()
        throw ( ::com::sun::star::uno::RuntimeException )
{
    ::uno::Sequence< OUString > aRet(1);
    aRet[0] = AVMEDIA_VLC_GRABBER_SERVICENAME;
    return aRet;
}

}
}