--- a/qtmobility/plugins/multimedia/gstreamer/mediacapture/qgstreamercapturesession.cpp Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/plugins/multimedia/gstreamer/mediacapture/qgstreamercapturesession.cpp Mon May 03 13:18:40 2010 +0300
@@ -44,7 +44,6 @@
#include "qgstreamermediacontainercontrol.h"
#include "qgstreameraudioencode.h"
#include "qgstreamervideoencode.h"
-#include "qgstreamerimageencode.h"
#include "qgstreamerbushelper.h"
#include <qmediarecorder.h>
@@ -67,6 +66,7 @@
:QObject(parent),
m_state(StoppedState),
m_pendingState(StoppedState),
+ m_waitingForEos(false),
m_pipelineMode(EmptyPipeline),
m_captureMode(captureMode),
m_audioInputFactory(0),
@@ -94,8 +94,7 @@
m_busHelper->installSyncEventFilter(this);
connect(m_busHelper, SIGNAL(message(QGstreamerMessage)), SLOT(busMessage(QGstreamerMessage)));
m_audioEncodeControl = new QGstreamerAudioEncode(this);
- m_videoEncodeControl = new QGstreamerVideoEncode(this);
- m_imageEncodeControl = new QGstreamerImageEncode(this);
+ m_videoEncodeControl = new QGstreamerVideoEncode(this);
m_recorderControl = new QGstreamerRecorderControl(this);
m_mediaContainerControl = new QGstreamerMediaContainerControl(this);
@@ -107,7 +106,6 @@
gst_object_unref(GST_OBJECT(m_pipeline));
}
-
GstElement *QGstreamerCaptureSession::buildEncodeBin()
{
bool ok = true;
@@ -329,164 +327,6 @@
return previewElement;
}
-
-static gboolean passImageFilter(GstElement *element,
- GstBuffer *buffer,
- void *appdata)
-{
- Q_UNUSED(element);
- Q_UNUSED(buffer);
-
- QGstreamerCaptureSession *session = (QGstreamerCaptureSession *)appdata;
- if (session->m_passImage || session->m_passPrerollImage) {
- session->m_passImage = false;
-
- if (session->m_passPrerollImage) {
- session->m_passPrerollImage = false;
- return TRUE;
- }
- session->m_passPrerollImage = false;
-
- QImage img;
-
- GstCaps *caps = gst_buffer_get_caps(buffer);
- if (caps) {
- GstStructure *structure = gst_caps_get_structure (caps, 0);
- gint width = 0;
- gint height = 0;
-
- if (structure &&
- gst_structure_get_int(structure, "width", &width) &&
- gst_structure_get_int(structure, "height", &height) &&
- width > 0 && height > 0) {
- if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) {
- guint32 fourcc = 0;
- gst_structure_get_fourcc(structure, "format", &fourcc);
-
- if (fourcc == GST_MAKE_FOURCC('I','4','2','0')) {
- img = QImage(width/2, height/2, QImage::Format_RGB32);
-
- const uchar *data = (const uchar *)buffer->data;
-
- for (int y=0; y<height; y+=2) {
- const uchar *yLine = data + y*width;
- const uchar *uLine = data + width*height + y*width/4;
- const uchar *vLine = data + width*height*5/4 + y*width/4;
-
- for (int x=0; x<width; x+=2) {
- const qreal Y = 1.164*(yLine[x]-16);
- const int U = uLine[x/2]-128;
- const int V = vLine[x/2]-128;
-
- int b = qBound(0, int(Y + 2.018*U), 255);
- int g = qBound(0, int(Y - 0.813*V - 0.391*U), 255);
- int r = qBound(0, int(Y + 1.596*V), 255);
-
- img.setPixel(x/2,y/2,qRgb(r,g,b));
- }
- }
- }
-
- } else if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
- QImage::Format format = QImage::Format_Invalid;
- int bpp = 0;
- gst_structure_get_int(structure, "bpp", &bpp);
-
- if (bpp == 24)
- format = QImage::Format_RGB888;
- else if (bpp == 32)
- format = QImage::Format_RGB32;
-
- if (format != QImage::Format_Invalid) {
- img = QImage((const uchar *)buffer->data,
- width,
- height,
- format);
- img.bits(); //detach
- }
- }
- }
- gst_caps_unref(caps);
- }
-
- static int signalIndex = session->metaObject()->indexOfSignal("imageCaptured(QString,QImage)");
- session->metaObject()->method(signalIndex).invoke(session,
- Qt::QueuedConnection,
- Q_ARG(QString,session->m_imageFileName),
- Q_ARG(QImage,img));
-
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static gboolean saveImageFilter(GstElement *element,
- GstBuffer *buffer,
- GstPad *pad,
- void *appdata)
-{
- Q_UNUSED(element);
- Q_UNUSED(pad);
- QGstreamerCaptureSession *session = (QGstreamerCaptureSession *)appdata;
-
- QString fileName = session->m_imageFileName;
-
- if (!fileName.isEmpty()) {
- QFile f(fileName);
- if (f.open(QFile::WriteOnly)) {
- f.write((const char *)buffer->data, buffer->size);
- f.close();
-
- static int signalIndex = session->metaObject()->indexOfSignal("imageSaved(QString)");
- session->metaObject()->method(signalIndex).invoke(session,
- Qt::QueuedConnection,
- Q_ARG(QString,fileName));
- }
- }
-
- return TRUE;
-}
-
-GstElement *QGstreamerCaptureSession::buildImageCapture()
-{
- GstElement *bin = gst_bin_new("image-capture-bin");
- GstElement *queue = gst_element_factory_make("queue", "queue-image-capture");
- GstElement *colorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-image-capture");
- GstElement *encoder = gst_element_factory_make("jpegenc", "image-encoder");
- GstElement *sink = gst_element_factory_make("fakesink","sink-image-capture");
-
- GstPad *pad = gst_element_get_static_pad(queue, "src");
- Q_ASSERT(pad);
- gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this);
-
- g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL);
- g_signal_connect(G_OBJECT(sink), "handoff",
- G_CALLBACK(saveImageFilter), this);
-
- gst_bin_add_many(GST_BIN(bin), queue, colorspace, encoder, sink, NULL);
- gst_element_link_many(queue, colorspace, encoder, sink, NULL);
-
- // add ghostpads
- pad = gst_element_get_static_pad(queue, "sink");
- Q_ASSERT(pad);
- gst_element_add_pad(GST_ELEMENT(bin), gst_ghost_pad_new("imagesink", pad));
- gst_object_unref(GST_OBJECT(pad));
-
- m_passImage = false;
- m_passPrerollImage = true;
- m_imageFileName = QString();
-
- return bin;
-}
-
-void QGstreamerCaptureSession::captureImage(const QString &fileName)
-{
- m_imageFileName = fileName;
- m_passImage = true;
-}
-
-
#define REMOVE_ELEMENT(element) { if (element) {gst_bin_remove(GST_BIN(m_pipeline), element); element = 0;} }
bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMode newMode)
@@ -500,7 +340,6 @@
REMOVE_ELEMENT(m_videoPreviewQueue);
REMOVE_ELEMENT(m_videoTee);
REMOVE_ELEMENT(m_encodeBin);
- REMOVE_ELEMENT(m_imageCaptureBin);
bool ok = true;
@@ -524,20 +363,17 @@
m_videoSrc = buildVideoSrc();
m_videoTee = gst_element_factory_make("tee", "video-preview-tee");
m_videoPreviewQueue = gst_element_factory_make("queue", "video-preview-queue");
- m_videoPreview = buildVideoPreview();
- m_imageCaptureBin = buildImageCapture();
+ m_videoPreview = buildVideoPreview();
- ok &= m_videoSrc && m_videoTee && m_videoPreviewQueue && m_videoPreview && m_imageCaptureBin;
+ ok &= m_videoSrc && m_videoTee && m_videoPreviewQueue && m_videoPreview;
if (ok) {
gst_bin_add_many(GST_BIN(m_pipeline), m_videoSrc, m_videoTee,
- m_videoPreviewQueue, m_videoPreview,
- m_imageCaptureBin, NULL);
+ m_videoPreviewQueue, m_videoPreview, NULL);
ok &= gst_element_link(m_videoSrc, m_videoTee);
ok &= gst_element_link(m_videoTee, m_videoPreviewQueue);
ok &= gst_element_link(m_videoPreviewQueue, m_videoPreview);
- ok &= gst_element_link(m_videoTee, m_imageCaptureBin);
}
}
break;
@@ -693,7 +529,7 @@
void QGstreamerCaptureSession::setState(QGstreamerCaptureSession::State newState)
{
- if (newState == m_pendingState)
+ if (newState == m_pendingState && !m_waitingForEos)
return;
m_pendingState = newState;
@@ -714,6 +550,23 @@
}
if (newMode != m_pipelineMode) {
+ if (m_pipelineMode == PreviewAndRecordingPipeline) {
+ if (!m_waitingForEos) {
+ m_waitingForEos = true;
+ //qDebug() << "Waiting for EOS";
+ //with live sources it's necessary to send EOS even to pipeline
+ //before going to STOPPED state
+ gst_element_send_event(m_pipeline, gst_event_new_eos());
+ return;
+ } else {
+ m_waitingForEos = false;
+ //qDebug() << "EOS received";
+ }
+ }
+
+ //select suitable default codecs/containers, if necessary
+ m_recorderControl->applySettings();
+
gst_element_set_state(m_pipeline, GST_STATE_NULL);
//It would be better to do this async. but
@@ -852,6 +705,11 @@
case GST_MESSAGE_DURATION:
break;
+ case GST_MESSAGE_EOS:
+ if (m_waitingForEos)
+ setState(m_pendingState);
+ break;
+
case GST_MESSAGE_STATE_CHANGED:
{