~ubuntu-branches/ubuntu/karmic/gnash/karmic

« back to all changes in this revision

Viewing changes to libmedia/gst/VideoDecoderGst.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2008-10-13 14:29:49 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20081013142949-f6qdvnu4mn05ltdc
Tags: 0.8.4~~bzr9980-0ubuntu1
* new upstream release 0.8.4 (LP: #240325)
* ship new lib usr/lib/gnash/libmozsdk.so.* in mozilla-plugin-gnash
  - update debian/mozilla-plugin-gnash.install
* ship new lib usr/lib/gnash/libgnashnet.so.* in gnash-common
  - update debian/gnash-common.install
* add basic debian/build_head script to build latest CVS head packages.
  - add debian/build_head
* new sound architecture requires build depend on libsdl1.2-dev
  - update debian/control
* head build script now has been completely migrated to bzr (upstream +
  ubuntu)
  - update debian/build_head
* disable kde gui until klash/qt4 has been fixed; keep kde packages as empty
  packages for now.
  - update debian/rules
  - debian/klash.install
  - debian/klash.links
  - debian/klash.manpages
  - debian/konqueror-plugin-gnash.install
* drop libkonq5-dev build dependency accordingly
  - update debian/control
* don't install headers manually anymore. gnash doesnt provide a -dev
  package after all
  - update debian/rules
* update libs installed in gnash-common; libgnashserver-*.so is not available
  anymore (removed); in turn we add the new libgnashcore-*.so
  - update debian/gnash-common.install
* use -Os for optimization and properly pass CXXFLAGS=$(CFLAGS) to configure
  - update debian/rules
* touch firefox .autoreg in postinst of mozilla plugin
  - update debian/mozilla-plugin-gnash.postinst
* link gnash in ubufox plugins directory for the plugin alternative switcher
  - add debian/mozilla-plugin-gnash.links
* suggest ubufox accordingly
  - update debian/control
* add new required build-depends on libgif-dev
  - update debian/control
* add Xb-Npp-Description and Xb-Npp-File as new plugin database meta data
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
// along with this program; if not, write to the Free Software
17
17
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 
19
 
// $Id: VideoDecoderGst.cpp,v 1.15.2.2 2008/02/27 20:55:02 bjacques Exp $
20
19
 
21
20
#ifdef HAVE_CONFIG_H
22
21
#include "gnashconfig.h"
23
22
#endif
24
23
 
25
24
#include "VideoDecoderGst.h"
26
 
#include "gstappsink.h"
27
 
#include "gstappsrc.h"
28
 
 
 
25
#include "MediaParserGst.h"
 
26
#include "GstUtil.h"
29
27
 
30
28
namespace gnash {
31
29
namespace media {
32
30
 
33
 
// gstappsrc -> decodebin -> (decoder) -> ffmpegcolorspace -> gstappsink (with rgb caps)
34
 
 
35
31
// TODO: implement proper seeking.
36
32
 
 
33
VideoDecoderGst::VideoDecoderGst(GstCaps* caps)
 
34
{
 
35
    // init GStreamer. TODO: what about doing this in MediaHandlerGst ctor?
 
36
    gst_init (NULL, NULL);
 
37
 
 
38
    setup(caps);
 
39
}
 
40
 
 
41
 
37
42
VideoDecoderGst::VideoDecoderGst(videoCodecType codec_type, int width, int height)
38
 
 : _appsink(NULL),
39
 
   _colorspace(NULL)
40
43
{
41
 
  gst_init (NULL, NULL);
42
 
  
43
 
  _pipeline = gst_pipeline_new (NULL);
 
44
    // init GStreamer. TODO: what about doing this in MediaHandlerGst ctor?
 
45
    gst_init (NULL, NULL);
44
46
 
45
 
  _appsrc = gst_element_factory_make ("appsrc", NULL);
46
 
  
47
 
  GstElement* decoder = NULL;
48
 
  
49
47
  GstCaps* caps;  
50
48
  switch (codec_type) {
51
49
    case VIDEO_CODEC_H263:
52
 
      decoder = gst_element_factory_make ("ffdec_flv", NULL);
53
50
      caps = gst_caps_new_simple ("video/x-flash-video",
54
 
                                      "width", G_TYPE_INT, width,
55
 
                                      "height", G_TYPE_INT, height,   
56
51
                                      NULL);
57
52
      break;
58
53
    case VIDEO_CODEC_VP6:
 
54
      caps = gst_caps_new_simple ("video/x-vp6-flash",
 
55
                                      NULL);
 
56
      break;
59
57
    case VIDEO_CODEC_VP6A:
60
 
      decoder = gst_element_factory_make ("ffdec_vp6f", NULL);
61
 
      caps = gst_caps_new_simple ("video/x-vp6-flash",
62
 
                                      "width", G_TYPE_INT, width,
63
 
                                      "height", G_TYPE_INT, height,     
 
58
      caps = gst_caps_new_simple ("video/x-vp6-alpha",
64
59
                                      NULL);
65
60
      break;      
66
61
    case VIDEO_CODEC_SCREENVIDEO:
67
62
    case VIDEO_CODEC_SCREENVIDEO2:
68
 
      decoder = gst_element_factory_make ("ffdec_flashsv", NULL);
69
63
      caps = gst_caps_new_simple ("video/x-flash-screen",
70
 
                                      "width", G_TYPE_INT, width,
71
 
                                      "height", G_TYPE_INT, height,
72
64
                                      NULL);
73
65
      break;
74
66
    case 0:
75
 
      log_debug("Video codec is zero.  Streaming video expected later.");
76
 
      gst_object_unref (GST_OBJECT (_pipeline));
77
 
      _pipeline = NULL;
 
67
      throw MediaException(_("Video codec is zero.  Streaming video expected later."));
78
68
      break;
79
69
    default:
80
 
      log_error("No support for this video codec. %d", codec_type);
81
 
      gst_object_unref (GST_OBJECT (_pipeline));
82
 
      _pipeline = NULL;
 
70
      boost::format msg = boost::format(_("No support for video codec %d.")) % (int)codec_type;
 
71
      throw MediaException(msg.str());
 
72
 
83
73
      return;
84
74
  }
85
75
  
86
 
  if (!decoder) {
87
 
    log_error(_("failed to initialize the video decoder. Embedded video "
88
 
                "playback will not be available; consider installing "
89
 
                "gstreamer-ffmpeg."));
90
 
    gst_object_unref (GST_OBJECT (_pipeline));
91
 
    _pipeline = NULL;
92
 
    return;
93
 
  }
94
 
  
95
 
  gst_app_src_set_caps (GST_APP_SRC(_appsrc), caps);
96
 
  gst_caps_unref(caps);
97
 
 
98
 
  _colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
99
 
 
100
 
  _appsink = gst_element_factory_make ("appsink", NULL);
101
 
 
102
 
 
103
 
  caps = gst_caps_new_simple ("video/x-raw-rgb", NULL);
104
 
 
105
 
  gst_app_sink_set_caps(GST_APP_SINK(_appsink), caps);
106
 
 
107
 
  gst_caps_unref (caps);
108
 
 
109
 
 
110
 
  gst_bin_add_many (GST_BIN (_pipeline), _appsrc, decoder, _colorspace, _appsink, NULL);
111
 
 
112
 
  gst_element_link_many(_appsrc, decoder, _colorspace, _appsink, NULL);
113
 
  
114
 
  gst_base_src_set_live(GST_BASE_SRC(_appsrc), TRUE);
115
 
 
116
 
  gst_element_set_state (GST_ELEMENT (_pipeline), GST_STATE_PLAYING);
 
76
  setup(caps);
 
77
  
117
78
}
118
79
 
 
80
 
119
81
VideoDecoderGst::~VideoDecoderGst()
120
82
{
121
 
  if (_pipeline) {
122
 
    gst_element_set_state (GST_ELEMENT (_pipeline), GST_STATE_NULL);
123
 
    gst_object_unref (GST_OBJECT (_pipeline));
124
 
  }
 
83
    swfdec_gst_decoder_push_eos(&_decoder);
 
84
    swfdec_gst_decoder_finish(&_decoder);
 
85
}
 
86
 
 
87
void
 
88
VideoDecoderGst::setup(GstCaps* srccaps)
 
89
{
 
90
    if (!srccaps) {
 
91
        throw MediaException(_("VideoDecoderGst: internal error (caps creation failed)"));      
 
92
    }
 
93
 
 
94
    bool success = GstUtil::check_missing_plugins(srccaps);
 
95
    if (!success) {
 
96
        throw MediaException(_("Couldn't find a plugin for video type ..."));
 
97
    }
 
98
 
 
99
    GstCaps* sinkcaps = gst_caps_new_simple ("video/x-raw-rgb", "bpp", G_TYPE_INT, 24,
 
100
                                             "depth", G_TYPE_INT, 24,
 
101
                                             NULL);
 
102
    if (!sinkcaps) {
 
103
        throw MediaException(_("VideoDecoderGst: internal error (caps creation failed)"));      
 
104
    }
 
105
 
 
106
    bool rv = swfdec_gst_decoder_init (&_decoder, srccaps, sinkcaps, "ffmpegcolorspace", NULL);
 
107
    if (!rv) {
 
108
        throw MediaException(_("VideoDecoderGst: initialisation failed."));      
 
109
    }
 
110
 
 
111
    gst_caps_unref (srccaps);
 
112
    gst_caps_unref (sinkcaps);
125
113
}
126
114
 
127
115
void
128
116
VideoDecoderGst::push(const EncodedVideoFrame& frame)
129
117
{
130
 
  if (!_pipeline) {
131
 
    return;
132
 
  }
133
 
  
134
 
  GstBuffer* buffer = gst_buffer_new();
135
 
  
136
 
  GST_BUFFER_DATA(buffer) = frame.data();
137
 
        GST_BUFFER_SIZE(buffer) = frame.dataSize();     
138
 
        GST_BUFFER_OFFSET(buffer) = frame.frameNum();
139
 
        GST_BUFFER_TIMESTAMP(buffer) = GST_CLOCK_TIME_NONE;
140
 
        GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;
141
 
  
142
 
  gst_app_src_push_buffer (GST_APP_SRC(_appsrc), buffer);
143
 
  
144
 
  checkMessages();
 
118
    GstBuffer* buffer;
 
119
    
 
120
    EncodedExtraGstData* extradata = dynamic_cast<EncodedExtraGstData*>(frame.extradata.get());
 
121
    
 
122
    if (extradata) {
 
123
        buffer = extradata->buffer;
 
124
    } else {
 
125
        buffer = gst_buffer_new();
 
126
 
 
127
        GST_BUFFER_DATA(buffer) = const_cast<uint8_t*>(frame.data());
 
128
        GST_BUFFER_SIZE(buffer) = frame.dataSize();
 
129
        GST_BUFFER_OFFSET(buffer) = frame.frameNum();
 
130
        GST_BUFFER_TIMESTAMP(buffer) = GST_CLOCK_TIME_NONE;
 
131
        GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;
 
132
    }
 
133
  
 
134
    bool success = swfdec_gst_decoder_push(&_decoder, buffer);
 
135
    if (!success) {
 
136
        log_error(_("VideoDecoderGst: buffer push failed."));
 
137
    }
145
138
}
146
139
  
147
140
 
148
 
std::auto_ptr<image::rgb>
 
141
std::auto_ptr<image::ImageBase>
149
142
VideoDecoderGst::pop()
150
143
{
151
 
  if (!_pipeline) {
152
 
    return std::auto_ptr<image::rgb>();
153
 
  }
154
 
 
155
 
  checkMessages();
156
 
  
157
 
  GstBuffer* buffer = gst_app_sink_pull_buffer_timed (GST_APP_SINK(_appsink));
158
 
  
159
 
  if (!buffer) {
160
 
    return std::auto_ptr<image::rgb>();
161
 
  }
162
 
  
163
 
  GstCaps* caps = gst_buffer_get_caps(buffer);
164
 
 
165
 
  assert(gst_caps_get_size(caps) == 1);
166
 
  
167
 
  GstStructure* structure = gst_caps_get_structure (caps, 0);
168
 
 
169
 
  gint height, width;
170
 
 
171
 
  gst_structure_get_int (structure, "width", &width);
172
 
  gst_structure_get_int (structure, "height", &height);
173
 
  
174
 
  gst_caps_unref(caps);
175
 
  
176
 
  std::auto_ptr<image::rgb> ret(new gnashGstBuffer(buffer, width, height));
177
 
  
178
 
  return ret;
 
144
    GstBuffer * buffer = swfdec_gst_decoder_pull (&_decoder);
 
145
 
 
146
    if (!buffer) {
 
147
        return std::auto_ptr<image::ImageBase>();
 
148
    }
 
149
  
 
150
    GstCaps* caps = gst_buffer_get_caps(buffer);
 
151
 
 
152
    assert(gst_caps_get_size(caps) == 1);
 
153
  
 
154
    GstStructure* structure = gst_caps_get_structure (caps, 0);
 
155
 
 
156
    gint height, width;
 
157
 
 
158
    gst_structure_get_int (structure, "width", &width);
 
159
    gst_structure_get_int (structure, "height", &height);
 
160
  
 
161
    gst_caps_unref(caps);
 
162
  
 
163
    std::auto_ptr<image::ImageBase> ret(new gnashGstBuffer(buffer, width, height));
 
164
  
 
165
    return ret;
179
166
}
180
167
  
181
168
 
182
169
bool
183
170
VideoDecoderGst::peek()
184
171
{
185
 
  if (!_pipeline) {
186
 
    return false;
187
 
  }
188
 
 
189
 
  return gst_app_sink_peek_buffer (GST_APP_SINK(_appsink));
190
 
}
191
 
 
192
 
void
193
 
VideoDecoderGst::checkMessages() // any messages for me?
194
 
{
195
 
  if (!_pipeline) {
196
 
    return;
197
 
  }
198
 
 
199
 
  GstBus* bus = gst_element_get_bus(_pipeline);
200
 
 
201
 
  while (gst_bus_have_pending(bus)) {
202
 
    GstMessage* msg = gst_bus_pop(bus);
203
 
    handleMessage(msg);
204
 
 
205
 
    gst_message_unref(msg);
206
 
  }
207
 
 
208
 
  gst_object_unref(GST_OBJECT(bus));
209
 
}
210
 
 
211
 
void
212
 
VideoDecoderGst::handleMessage (GstMessage *message)
213
 
{
214
 
#if 0
215
 
  g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
216
 
#endif
217
 
 
218
 
  switch (GST_MESSAGE_TYPE (message)) {
219
 
    case GST_MESSAGE_ERROR:
220
 
    {
221
 
      GError *err;
222
 
      gchar *debug;
223
 
      gst_message_parse_error (message, &err, &debug);
224
 
      
225
 
      log_error(_("Embedded video playback halted; module %s reported: %s\n"),
226
 
                gst_element_get_name(GST_MESSAGE_SRC (message)), err->message);
227
 
      
228
 
      g_error_free (err);
229
 
      g_free (debug);
230
 
      
231
 
      // Clear any buffers.
232
 
      gst_element_set_state (_pipeline, GST_STATE_NULL);
233
 
 
234
 
      break;
235
 
    }
236
 
    case GST_MESSAGE_EOS:
237
 
      log_debug(_("NetStream has reached the end of the stream."));
238
 
 
239
 
      break;
240
 
    
241
 
    default:
242
 
    {
243
 
#if 0
244
 
      g_print("unhandled message\n");
245
 
#endif
246
 
    }
247
 
  }
248
 
 
 
172
  return !g_queue_is_empty (_decoder.queue);
249
173
}
250
174
 
251
175