Further work on gstreamer video support, not working yet
This commit is contained in:
1 parent
1bc7ff8944
commit
5264e1f291
13 files changed
+273
-20
No files matched your search
@@ -122,7 +122,7 @@
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>gstreamer-1.0.lib;gstcontroller-1.0.lib;gobject-2.0.lib;glib-2.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>gstreamer-1.0.lib;gstcontroller-1.0.lib;gobject-2.0.lib;glib-2.0.lib;gstapp-1.0.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWin|Win32'">
|
||||
|
||||
@@ -55,9 +55,11 @@ DllExport bool CloseVideo(int Stream)
|
||||
map<int,GstreamerVideoStream*>::iterator it = VideoStreams.find(Stream);
|
||||
if(it != VideoStreams.end())
|
||||
{
|
||||
return it->second->CloseVideo();
|
||||
delete it->second;
|
||||
VideoStreams.erase(it);
|
||||
}
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
DllExport int GetVideoNumStreams()
|
||||
@@ -75,12 +77,12 @@ DllExport float GetVideoLength(int Stream)
|
||||
else return -1.0;
|
||||
}
|
||||
|
||||
DllExport UINT8* GetFrame(int Stream, float Time, float &VideoTime)
|
||||
DllExport guint8* GetFrame(int Stream, float Time, float &VideoTime, int &Size, int &Width, int &Height)
|
||||
{
|
||||
map<int,GstreamerVideoStream*>::iterator it = VideoStreams.find(Stream);
|
||||
if(it != VideoStreams.end())
|
||||
{
|
||||
return it->second->GetFrame(Time, VideoTime);
|
||||
return it->second->GetFrame(Time, VideoTime, Size, Width, Height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +128,30 @@ DllExport bool Finished(int Stream)
|
||||
map<int,GstreamerVideoStream*>::iterator it = VideoStreams.find(Stream);
|
||||
if(it != VideoStreams.end())
|
||||
{
|
||||
return it->second->Finished();
|
||||
return it->second->IsFinished();
|
||||
}
|
||||
else return true;
|
||||
}
|
||||
|
||||
DllExport void UpdateVideo(void)
|
||||
{
|
||||
map<int, GstreamerVideoStream*>::iterator p = VideoStreams.begin();
|
||||
|
||||
while(p != VideoStreams.end())
|
||||
{
|
||||
if(p->second->Closed)
|
||||
{
|
||||
delete p->second;
|
||||
VideoStreams.erase(p++);
|
||||
}
|
||||
else {
|
||||
p->second->UpdateVideo();
|
||||
++p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LogVideoError(const char* msg)
|
||||
{
|
||||
Log(msg);
|
||||
}
|
||||
@@ -20,7 +20,7 @@ using namespace std;
|
||||
DllExport int GetVideoNumStreams();
|
||||
|
||||
DllExport float GetVideoLength(int StreamID);
|
||||
DllExport UINT8* GetFrame(int StreamID, float Time, float &VideoTime);
|
||||
DllExport guint8* GetFrame(int StreamID, float Time, float &VideoTime, int &Size, int &Width, int &Height);
|
||||
DllExport bool Skip(int StreamID, float Start, float Gap);
|
||||
DllExport void SetVideoLoop(int StreamID, bool Loop);
|
||||
DllExport void PauseVideo(int StreamID);
|
||||
@@ -28,5 +28,7 @@ using namespace std;
|
||||
|
||||
DllExport bool Finished(int StreamID);
|
||||
|
||||
DllExport void UpdateVideo();
|
||||
|
||||
void LogVideoError(const char* msg);
|
||||
|
||||
@@ -1,56 +1,190 @@
|
||||
#include "stdafx.h"
|
||||
#include "GstreamerVideoStream.h"
|
||||
|
||||
typedef enum {
|
||||
GST_PLAY_FLAG_VIDEO = (1 << 0),
|
||||
GST_PLAY_FLAG_AUDIO = (1 << 1),
|
||||
GST_PLAY_FLAG_TEXT = (1 << 2),
|
||||
GST_PLAY_FLAG_VIS = (1 << 3),
|
||||
GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4),
|
||||
GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5),
|
||||
GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6),
|
||||
GST_PLAY_FLAG_DOWNLOAD = (1 << 7),
|
||||
GST_PLAY_FLAG_BUFFERING = (1 << 8),
|
||||
GST_PLAY_FLAG_DEINTERLACE = (1 << 9),
|
||||
GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10)
|
||||
} GstPlayFlags;
|
||||
|
||||
GstreamerVideoStream::GstreamerVideoStream(int ID)
|
||||
{
|
||||
this->ID = ID;
|
||||
|
||||
Loop = false;
|
||||
|
||||
Running = true;
|
||||
|
||||
Paused = false;
|
||||
Finished = false;
|
||||
Closed = false;
|
||||
|
||||
Duration = -1.0;
|
||||
}
|
||||
|
||||
|
||||
GstreamerVideoStream::~GstreamerVideoStream(void)
|
||||
{
|
||||
CloseVideo();
|
||||
}
|
||||
|
||||
int GstreamerVideoStream::LoadVideo(const wchar_t* Filename)
|
||||
{
|
||||
Element = gst_element_factory_make("playbin", "playbin");
|
||||
|
||||
|
||||
Appsink = (GstAppSink*) gst_element_factory_make("appsink", "appsink");
|
||||
|
||||
Bus = gst_element_get_bus(Element);
|
||||
if(!Element)
|
||||
{
|
||||
LogVideoError ("Could not create element!");
|
||||
return -1;
|
||||
}
|
||||
g_object_set(Element, "uri", Filename, NULL);
|
||||
//g_object_set(Element, "video-sink", Appsink, NULL);
|
||||
g_object_set(Element, "flags", GST_PLAY_FLAG_VIDEO, NULL);
|
||||
|
||||
//GstCaps *caps = gst_caps_new_any();
|
||||
|
||||
//gst_caps_set_value(caps, "format", (GValue*)"RGBA");
|
||||
//gst_app_sink_set_caps(Appsink, caps);
|
||||
|
||||
gst_element_set_state(Element, GST_STATE_PLAYING);
|
||||
//gst_bus_timed_pop_filtered(Bus, -1, GST_MESSAGE_ASYNC_DONE);
|
||||
Paused = true;
|
||||
RefreshDuration();
|
||||
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
||||
bool GstreamerVideoStream::CloseVideo()
|
||||
{
|
||||
if(Element)
|
||||
gst_element_set_state(Element, GST_STATE_NULL);
|
||||
if(Appsink)
|
||||
gst_object_unref(Appsink);
|
||||
if(Bus)
|
||||
gst_object_unref(Bus);
|
||||
if(Element)
|
||||
gst_object_unref(Element);
|
||||
return true;
|
||||
}
|
||||
|
||||
float GstreamerVideoStream::GetVideoLength()
|
||||
{
|
||||
return 0.0;
|
||||
if(Duration <= 0)
|
||||
RefreshDuration();
|
||||
return Duration;
|
||||
}
|
||||
|
||||
UINT8* GstreamerVideoStream::GetFrame(float Time, float &VideoTime)
|
||||
guint8* GstreamerVideoStream::GetFrame(float Time, float &VideoTime, int &Size, int &Width, int &Height)
|
||||
{
|
||||
/*GstSample *sample;
|
||||
GstBuffer *buffer;
|
||||
GstElement *sink;
|
||||
|
||||
sample = gst_app_sink_pull_sample(Appsink);
|
||||
buffer = gst_sample_get_buffer(sample);
|
||||
|
||||
g_object_get(Element, "video-sink", &sink, NULL);
|
||||
|
||||
gst_buffer_map(buffer, &Mapinfo, GST_MAP_READ);
|
||||
|
||||
VideoTime = (float) (buffer->pts / GST_SECOND);
|
||||
Size = Mapinfo.size;
|
||||
return Mapinfo.data; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GstreamerVideoStream::Skip(float Start, float Gap)
|
||||
{
|
||||
return true;
|
||||
if(!gst_element_seek_simple(Element, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), (Start + Gap) * GST_SECOND))
|
||||
{
|
||||
LogVideoError("Seek failed");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GstreamerVideoStream::SetVideoLoop(bool Loop)
|
||||
{
|
||||
this->Loop = Loop;
|
||||
}
|
||||
|
||||
void GstreamerVideoStream::PauseVideo()
|
||||
{
|
||||
if(Element)
|
||||
gst_element_set_state(Element, GST_STATE_PAUSED);
|
||||
}
|
||||
|
||||
void GstreamerVideoStream::ResumeVideo()
|
||||
{
|
||||
if(Element)
|
||||
gst_element_set_state(Element, GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
bool GstreamerVideoStream::Finished()
|
||||
bool GstreamerVideoStream::IsFinished()
|
||||
{
|
||||
return true;
|
||||
return Finished;
|
||||
}
|
||||
|
||||
void GstreamerVideoStream::RefreshDuration()
|
||||
{
|
||||
if(Element)
|
||||
{
|
||||
gint64 time;
|
||||
if(!gst_element_query_duration(Element, GST_FORMAT_TIME, &time)) {
|
||||
LogVideoError("Could not query duration");
|
||||
}
|
||||
Duration = (gfloat)((gdouble)(time/GST_SECOND));
|
||||
}
|
||||
}
|
||||
|
||||
void GstreamerVideoStream::UpdateVideo()
|
||||
{
|
||||
if(Running) {
|
||||
Message = gst_bus_pop (Bus);
|
||||
|
||||
/* Parse message */
|
||||
if (Message != NULL) {
|
||||
GError *err;
|
||||
gchar *debug_info;
|
||||
string m;
|
||||
|
||||
switch (GST_MESSAGE_TYPE (Message)) {
|
||||
case GST_MESSAGE_ERROR:
|
||||
gst_message_parse_error (Message, &err, &debug_info);
|
||||
m = err->message;
|
||||
LogVideoError(m.c_str());
|
||||
g_clear_error (&err);
|
||||
g_free (debug_info);
|
||||
break;
|
||||
case GST_MESSAGE_DURATION_CHANGED:
|
||||
RefreshDuration();
|
||||
break;
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
break;
|
||||
case GST_MESSAGE_EOS:
|
||||
if(Loop)
|
||||
Skip(0, 0);
|
||||
else
|
||||
Finished = true;
|
||||
break;
|
||||
default:
|
||||
/* We should not reach here */
|
||||
//LogError ("Unexpected message received.\n");
|
||||
break;
|
||||
}
|
||||
gst_message_unref (Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
#pragma once
|
||||
#include "gst/gst.h"
|
||||
#include "GstreamerVideo.h"
|
||||
#include "gst\app\gstappsink.h"
|
||||
|
||||
using namespace std;
|
||||
class GstreamerVideoStream
|
||||
{
|
||||
|
||||
public:
|
||||
int ID;
|
||||
bool Closed;
|
||||
|
||||
GstreamerVideoStream(int ID);
|
||||
~GstreamerVideoStream(void);
|
||||
@@ -14,12 +18,33 @@ public:
|
||||
bool CloseVideo();
|
||||
|
||||
float GetVideoLength();
|
||||
UINT8* GetFrame(float Time, float &VideoTime);
|
||||
guint8* GetFrame(float Time, float &VideoTime, int &Size, int &Width, int &Height);
|
||||
bool Skip(float Start, float Gap);
|
||||
void SetVideoLoop(bool Loop);
|
||||
void PauseVideo();
|
||||
void ResumeVideo();
|
||||
|
||||
bool Finished();
|
||||
void UpdateVideo();
|
||||
|
||||
bool IsFinished();
|
||||
|
||||
private:
|
||||
GstAppSink *Appsink;
|
||||
GstElement *Element;
|
||||
GstBus *Bus;
|
||||
GstMessage *Message;
|
||||
GstMapInfo Mapinfo;
|
||||
|
||||
gboolean Loop;
|
||||
|
||||
gboolean Running;
|
||||
|
||||
gboolean Paused;
|
||||
gboolean Finished;
|
||||
|
||||
gfloat Duration;
|
||||
|
||||
void RefreshDuration();
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
@@ -319,6 +319,7 @@ namespace Vocaluxe.Base
|
||||
Mouse.CopyEvents();
|
||||
Keys.CopyEvents();
|
||||
|
||||
CVideo.Update();
|
||||
CSound.Update();
|
||||
CBackgroundMusic.Update();
|
||||
CInput.Update();
|
||||
|
||||
@@ -95,6 +95,11 @@ namespace Vocaluxe.Base
|
||||
return _VideoDecoder.Finished(StreamID);
|
||||
}
|
||||
|
||||
public static void Update()
|
||||
{
|
||||
_VideoDecoder.Update();
|
||||
}
|
||||
|
||||
#endregion Interface
|
||||
|
||||
#endregion VideoDecoder
|
||||
|
||||
@@ -68,6 +68,10 @@ namespace Vocaluxe.Lib.Video
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
}
|
||||
|
||||
protected bool AlreadyAdded(int StreamID)
|
||||
{
|
||||
foreach (VideoStreams st in _Streams)
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Vocaluxe.Base;
|
||||
using Vocaluxe.Lib.Video.Gstreamer;
|
||||
using Vocaluxe.Menu;
|
||||
|
||||
namespace Vocaluxe.Lib.Video
|
||||
{
|
||||
class CVideoDecoderGstreamer : IVideoDecoder
|
||||
{
|
||||
#region log
|
||||
public CGstreamerVideoWrapper.LogCallback Log;
|
||||
|
||||
private void LogHandler(string text)
|
||||
{
|
||||
CLog.LogError(text);
|
||||
|
||||
}
|
||||
#endregion log
|
||||
|
||||
public bool Init()
|
||||
{
|
||||
return CGstreamerVideoWrapper.InitVideo();
|
||||
bool retval = CGstreamerVideoWrapper.InitVideo();
|
||||
Log = new CGstreamerVideoWrapper.LogCallback(LogHandler);
|
||||
GC.SuppressFinalize(Log);
|
||||
CGstreamerVideoWrapper.SetVideoLogCallback(Log);
|
||||
return retval;
|
||||
}
|
||||
|
||||
public void CloseAll()
|
||||
@@ -19,7 +35,15 @@ namespace Vocaluxe.Lib.Video
|
||||
|
||||
public int Load(string VideoFileName)
|
||||
{
|
||||
return CGstreamerVideoWrapper.LoadVideo(VideoFileName);
|
||||
int i = -1;
|
||||
try
|
||||
{
|
||||
Uri u = new Uri(VideoFileName);
|
||||
i = CGstreamerVideoWrapper.LoadVideo(u.AbsoluteUri);
|
||||
return i;
|
||||
}
|
||||
catch (Exception e) { }
|
||||
return i;
|
||||
}
|
||||
|
||||
public bool Close(int StreamID)
|
||||
@@ -37,9 +61,11 @@ namespace Vocaluxe.Lib.Video
|
||||
return CGstreamerVideoWrapper.GetVideoLength(StreamID);
|
||||
}
|
||||
|
||||
public bool GetFrame(int StreamID, ref Menu.STexture Frame, float Time, ref float VideoTime)
|
||||
public bool GetFrame(int StreamID, ref STexture Frame, float Time, ref float VideoTime)
|
||||
{
|
||||
IntPtr buffer = CGstreamerVideoWrapper.GetFrame(StreamID, Time, ref VideoTime);
|
||||
//IntPtr buffer = CGstreamerVideoWrapper.GetFrame(StreamID, Time, ref VideoTime);
|
||||
byte[] data = new byte[4 * 4 * 4];
|
||||
UploadNewFrame(ref Frame, ref data, 4, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,5 +93,23 @@ namespace Vocaluxe.Lib.Video
|
||||
{
|
||||
return CGstreamerVideoWrapper.Finished(StreamID);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
CGstreamerVideoWrapper.UpdateVideo();
|
||||
}
|
||||
|
||||
private void UploadNewFrame(ref STexture frame, ref byte[] Data, int Width, int Height)
|
||||
{
|
||||
if (frame.index == -1 || Width != frame.width || Height != frame.height)
|
||||
{
|
||||
CDraw.RemoveTexture(ref frame);
|
||||
frame = CDraw.AddTexture(Width, Height, ref Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
CDraw.UpdateTexture(ref frame, ref Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,16 @@ namespace Vocaluxe.Lib.Video.Gstreamer
|
||||
[DllImport(Dll)]
|
||||
public static extern float GetVideoLength(int StreamID);
|
||||
|
||||
[DllImport(Dll)]
|
||||
public static extern IntPtr GetFrame(int StreamID, float Time, ref float VideoTime);
|
||||
[DllImport(Dll, EntryPoint="GetFrame")]
|
||||
public static extern IntPtr GetFrameNative(int StreamID, float Time, ref float VideoTime, ref int Size, ref int Width, ref int Height);
|
||||
|
||||
public static byte[] GetFrame(int StreamID, float Time, ref float VideoTime, ref int Size, ref int Width, ref int Height)
|
||||
{
|
||||
IntPtr buf = GetFrameNative(StreamID, Time, ref VideoTime, ref Size, ref Width, ref Height);
|
||||
byte[] buffer = new byte[Size];
|
||||
Marshal.Copy(buf, buffer, 0, Size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
[DllImport(Dll)]
|
||||
public static extern bool Skip(int StreamID, float Start, float Gap);
|
||||
@@ -61,5 +69,8 @@ namespace Vocaluxe.Lib.Video.Gstreamer
|
||||
[DllImport(Dll)]
|
||||
public static extern bool Finished(int StreamID);
|
||||
|
||||
[DllImport(Dll)]
|
||||
public static extern bool UpdateVideo();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -36,5 +36,7 @@ namespace Vocaluxe.Lib.Video
|
||||
void Resume(int StreamID);
|
||||
|
||||
bool Finished(int StreamID);
|
||||
|
||||
void Update();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in new issue
Block a user