This URL has Read-Only access.

Statistics
| Branch: | Tag: | Revision:

root / src / gst / videoSource.cpp @ c01d47e9

History | View | Annotate | Download (8.8 kB)

1
/* videoSource.cpp
2
 * Copyright (C) 2008-2009 Société des arts technologiques (SAT)
3
 * http://www.sat.qc.ca
4
 * All rights reserved.
5
 *
6
 * This file is part of [propulse]ART.
7
 *
8
 * [propulse]ART is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * [propulse]ART is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with [propulse]ART.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22

    
23
#include "util.h"
24

    
25
#include <sstream>
26
#include <boost/lexical_cast.hpp>
27

    
28
#include "gstLinkable.h"
29
#include "videoSource.h"
30
#include "pipeline.h"
31
#include "videoConfig.h"
32

    
33
#include "dv1394.h"
34
#include "dc1394.h"
35
#include "v4l2util.h"
36

    
37
#include "fileSource.h"
38

    
39

    
40
/// Constructor
41
VideoSource::VideoSource(Pipeline &pipeline, const VideoSourceConfig &config) : 
42
    pipeline_(pipeline),
43
    config_(config), 
44
    source_(0), 
45
    capsFilter_(0)
46
{}
47

    
48

    
49
/// Destructor
50
VideoSource::~VideoSource()
51
{
52
    pipeline_.remove(&capsFilter_);
53
    pipeline_.remove(&source_);
54
}
55

    
56
std::string VideoSource::defaultSrcCaps() const
57
{
58
    std::ostringstream capsStr;
59
    capsStr << "video/x-raw-yuv, width=" << config_.captureWidth()
60
        << ", height=" << config_.captureHeight() << ", framerate="
61
        << config_.framerate() << "000/1001, pixel-aspect-ratio=" 
62
        << config_.pixelAspectRatio();
63
    return capsStr.str();
64
}
65

    
66
std::string VideoSource::srcCaps() const
67
{
68
    return defaultSrcCaps();
69
}
70

    
71

    
72
/// Sets caps on capsfilter
73
void VideoSource::setCapsFilter(const std::string &capsStr)
74
{
75
    tassert(capsFilter_ != 0);
76
    GstCaps *videoCaps = gst_caps_from_string(capsStr.c_str());
77
    LOG_DEBUG("Setting caps to " << gst_caps_to_string(videoCaps));
78
    g_object_set(G_OBJECT(capsFilter_), "caps", videoCaps, NULL);
79

    
80
    gst_caps_unref(videoCaps);
81
}
82

    
83

    
84
/// Constructor
85
VideoTestSource::VideoTestSource(Pipeline &pipeline, const VideoSourceConfig &config) : 
86
    VideoSource(pipeline, config)
87
{
88
    source_ = pipeline_.makeElement(config_.source(), NULL);
89
    g_object_set(G_OBJECT(source_), "is-live", TRUE, NULL); // necessary for clocked callback to work
90

    
91
    capsFilter_ = pipeline_.makeElement("capsfilter", NULL);
92
    gstlinkable::link(source_, capsFilter_);
93
    setCapsFilter(srcCaps());
94
}
95

    
96
/// Destructor
97
VideoTestSource::~VideoTestSource()
98
{}
99

    
100

    
101
/// Constructor
102
VideoFileSource::VideoFileSource(Pipeline &pipeline, const VideoSourceConfig &config) : 
103
    VideoSource(pipeline, config), 
104
    identity_(pipeline_.makeElement("identity", NULL))
105
{
106
    tassert(config_.locationExists());
107
    g_object_set(identity_, "silent", TRUE, NULL);
108

    
109
    GstElement * queue = FileSource::acquireVideo(pipeline, config_.location());
110
    gstlinkable::link(queue, identity_);
111
}
112

    
113
/// Destructor
114
VideoFileSource::~VideoFileSource()
115
{
116
    pipeline_.remove(&identity_);
117
    FileSource::releaseVideo(config_.location());
118
}
119

    
120

    
121
/// Constructor
122
VideoDvSource::VideoDvSource(Pipeline &pipeline, const VideoSourceConfig &config) : 
123
    VideoSource(pipeline, config), 
124
    queue_(pipeline_.makeElement("queue", NULL)), 
125
    dvdec_(pipeline_.makeElement("dvdec", NULL))
126
{
127
    Dv1394::Instance(pipeline_)->setVideoSink(queue_);
128
    gstlinkable::link(queue_, dvdec_);
129
}
130

    
131

    
132
/// Destructor
133
VideoDvSource::~VideoDvSource()
134
{
135
    pipeline_.remove(&queue_);
136
    pipeline_.remove(&dvdec_);
137
    Dv1394::Instance(pipeline_)->unsetVideoSink();
138
}
139

    
140

    
141
bool VideoV4lSource::willModifyCaptureResolution() const 
142
{ 
143
    return v4l2util::captureWidth(deviceStr()) != config_.captureWidth() or  
144
        v4l2util::captureHeight(deviceStr()) != config_.captureHeight(); 
145
} 
146

    
147

    
148
VideoV4lSource::VideoV4lSource(Pipeline &pipeline, const VideoSourceConfig &config)
149
    : VideoSource(pipeline, config), expectedStandard_("NTSC"), actualStandard_("")
150
{
151
    source_ = pipeline_.makeElement(config_.source(), NULL);
152
    // set a v4l2src if given to config as an arg, otherwise use default
153
    if (config_.hasDeviceName() && config_.deviceExists())
154
        g_object_set(G_OBJECT(source_), "device", config_.deviceName(), NULL);
155

    
156
    if (!v4l2util::checkStandard(expectedStandard_, actualStandard_, deviceStr()))
157
        LOG_WARNING("V4l2 device " << deviceStr() << " is not set to expected standard " 
158
                << expectedStandard_ << ", it is " << actualStandard_);
159

    
160
    LOG_DEBUG("v4l width is " << v4l2util::captureWidth(deviceStr()));
161
    LOG_DEBUG("v4l height is " << v4l2util::captureHeight(deviceStr()));
162

    
163
    if (willModifyCaptureResolution())  
164
    {
165
        LOG_INFO("Changing v4l resolution to " << 
166
                config_.captureWidth() << "x" << config_.captureHeight());
167
        v4l2util::setFormatVideo(deviceStr(), config_.captureWidth(), config_.captureHeight());
168
    }
169

    
170
    capsFilter_ = pipeline_.makeElement("capsfilter", NULL);
171
    gstlinkable::link(source_, capsFilter_);
172

    
173
    setCapsFilter(srcCaps());
174
}
175

    
176

    
177
std::string VideoV4lSource::deviceStr() const
178
{
179
    gchar *device_cstr;
180
    g_object_get(G_OBJECT(source_), "device", &device_cstr, NULL);    // get actual used device
181

    
182
    std::string deviceString(device_cstr);        // stay safe from memory leaks
183
    g_free(device_cstr);
184
    return deviceString;
185
}
186

    
187

    
188
std::string VideoV4lSource::srcCaps() const
189
{
190
    std::ostringstream capsStr;
191

    
192
    std::string capsSuffix;
193
    if (actualStandard_ == "NTSC")
194
        capsSuffix = "30000/1001"; // NTSC is drop frame
195
    else if (actualStandard_ == "PAL")
196
        capsSuffix = "25/1"; // PAL is not drop frame
197
    else 
198
    {
199
        capsSuffix = boost::lexical_cast<std::string>(config_.framerate()); 
200
        capsSuffix += "/1";
201
        LOG_WARNING("Unsupported standard, " << actualStandard_
202
                << "trying to add framerate " << capsSuffix << " to caps");
203
    }
204

    
205
    if (v4l2util::isInterlaced(deviceStr()))
206
        capsSuffix +=", interlaced=true";
207

    
208
    capsSuffix += ", pixel-aspect-ratio=";
209
    capsSuffix += config_.pixelAspectRatio();
210

    
211
    capsStr << "video/x-raw-yuv, width=" << config_.captureWidth() << ", height=" 
212
        << config_.captureHeight() 
213
        << ", framerate="
214
        << capsSuffix;
215
    LOG_DEBUG("V4l2src caps are " << capsStr.str());
216

    
217
    return capsStr.str();
218
}
219

    
220

    
221
VideoDc1394Source::VideoDc1394Source(Pipeline &pipeline, const VideoSourceConfig &config) : 
222
    VideoSource(pipeline, config) 
223
{
224
    if (DC1394::areCamerasConnected())
225
        THROW_CRITICAL("No dc1394 camera connected");
226

    
227
    source_ = pipeline_.makeElement(config_.source(), NULL);
228
    if (config_.hasGUID())
229
        g_object_set(G_OBJECT(source_), "camera-number", DC1394::GUIDToCameraNumber(config_.GUID()), NULL);
230
    else if (config_.hasCameraNumber())
231
        g_object_set(G_OBJECT(source_), "camera-number", config_.cameraNumber(), NULL);
232
    else
233
        LOG_DEBUG("No valid camera-number or guid specified, using default camera number 0");
234
    /// TODO: test. this will hopefully help reduce the lag we're seeing with dc1394src
235
    g_object_set(G_OBJECT(source_), "buffer-size", DMA_BUFFER_SIZE_IN_FRAMES, NULL);
236

    
237
    capsFilter_ = pipeline_.makeElement("capsfilter", NULL);
238
    gstlinkable::link(source_, capsFilter_);
239

    
240
    setCapsFilter(srcCaps());
241
}
242

    
243

    
244
std::string VideoDc1394Source::srcCaps() const 
245
{ 
246
    typedef std::vector<std::string> ColourspaceList; 
247
    std::ostringstream capsStr; 
248
    int cameraNumber; 
249
    int mode = 0; 
250
    g_object_get(source_, "camera-number", &cameraNumber, NULL); 
251

    
252
    std::string colourSpace; 
253
    ColourspaceList spaces; 
254
    // if we support other colourspaces besides grayscale 
255
    if (!config_.forceGrayscale()) 
256
    { 
257
        /// favour rgb because we need to be have that colourspace for shared video buffer 
258
        spaces.push_back("rgb"); 
259
        spaces.push_back("yuv"); 
260
    } 
261
    spaces.push_back("gray"); 
262

    
263
    for (ColourspaceList::iterator space = spaces.begin(); mode == 0 and space != spaces.end(); ++space) 
264
    { 
265
        colourSpace = *space; 
266
        mode = DC1394::capsToMode(cameraNumber, config_.captureWidth(),  
267
                config_.captureHeight(), colourSpace, config_.framerate()); 
268
    } 
269

    
270
    // vmode takes into account resolution, bpp, depth 
271
    if (mode != 0) 
272
        capsStr << "video/x-raw-" << colourSpace << ", vmode=" << mode << ",framerate="<< config_.framerate() << "/1"; 
273
    else 
274
        THROW_CRITICAL("Could not find appropriate video mode for colourspace " 
275
                << colourSpace  << " and resolution " 
276
                << config_.captureWidth() << "x" << config_.captureHeight()); 
277

    
278
    if (DC1394::requiresMoreISOSpeed(mode)) 
279
    { 
280
        // FIXME: should set to b-mode too 
281
        LOG_DEBUG("Setting iso speed to 800"); 
282
        g_object_set(source_, "iso-speed", DC1394::MAX_ISO_SPEED, NULL); 
283
    } 
284
    return capsStr.str(); 
285
}
286