git-tfs-id: [http://tfs.userrendszerhaz.hu:8080/tfs/DefaultCollection]$/MediaCube...
authorVásáry Dániel <daniel.vasary@userrendszerhaz.hu>
Wed, 13 Jun 2018 21:35:35 +0000 (21:35 +0000)
committerVásáry Dániel <daniel.vasary@userrendszerhaz.hu>
Wed, 13 Jun 2018 21:35:35 +0000 (21:35 +0000)
23 files changed:
client/DxPlay/DxPlay.csproj
client/DxPlay/DxPlayer - Copy.cs [new file with mode: 0644]
client/DxPlay/DxPlayer.cs
client/DxPlay/LAVInterfaces.cs
client/DxPlay/PlayerGraph.cs [new file with mode: 0644]
server/-configuration/scheduledjobs.json
server/user.jobengine.executors/config/config.xml
server/user.jobengine.executors/config/scheduledjobs.json
server/user.jobengine.executors/jobtemplates/sys-check-lowres-integrity.xml [new file with mode: 0644]
server/user.jobengine.executors/jobtemplates/sys-recreate-length.xml [new file with mode: 0644]
server/user.jobengine.executors/jobtemplates/sys-recreate-lowres.xml [moved from server/user.jobengine.executors/jobtemplates/recreate-lowres.xml with 100% similarity]
server/user.jobengine.executors/src/user/jobengine/server/steps/CheckLOWRESIntegrity.java [new file with mode: 0644]
server/user.jobengine.executors/src/user/jobengine/server/steps/CopyForArchiveNEXIOMaterialsStep.java
server/user.jobengine.executors/src/user/jobengine/server/steps/CreateMissingLowresStep.java
server/user.jobengine.executors/src/user/jobengine/server/steps/TSMBackupStep.java
server/user.jobengine.executors/src/user/jobengine/server/steps/TranscodeFFAStranStep.java
server/user.jobengine.executors/src/user/jobengine/server/steps/TranscodeSELENIOStep.java
server/user.jobengine.osgi.commons/src/user/commons/FFAStransAPI.java
server/user.jobengine.osgi.db/sql/cleanup.sql
server/user.jobengine.osgi.server/WEB-INF/web.xml
server/user.jobengine.osgi.server/WEB-INF/zk.xml
server/user.jobengine.osgi.server/resources/i3-label_hu.properties
server/user.jobengine.osgi.server/test/user/jobengine/server/IT/Support.java

index a7959ef6503867a719b4e8203980440ca657a056..00defee432bc093e10d7989e383bbc4c277ead55 100644 (file)
     </Reference>\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <Compile Include="DxPlayer - Copy.cs" />\r
     <Compile Include="DxPlayer.cs" />\r
     <Compile Include="FilterGraphTools.cs" />\r
     <Compile Include="FlexibleMessageBox.cs" />\r
     </Compile>\r
     <Compile Include="Messages.cs" />\r
     <Compile Include="NativeMethods.cs" />\r
+    <Compile Include="PlayerGraph.cs" />\r
     <Compile Include="Program.cs" />\r
     <Compile Include="Properties\Resources.Designer.cs">\r
       <DependentUpon>Resources.resx</DependentUpon>\r
diff --git a/client/DxPlay/DxPlayer - Copy.cs b/client/DxPlay/DxPlayer - Copy.cs
new file mode 100644 (file)
index 0000000..79fed81
--- /dev/null
@@ -0,0 +1,689 @@
+using System;\r
+using System.Drawing;\r
+using System.Runtime.InteropServices;\r
+using System.Diagnostics;\r
+using System.Windows.Forms;\r
+using System.Threading;\r
+\r
+using DirectShowLib;\r
+using DirectShowLib.Utils;\r
+using Microsoft.Win32.SafeHandles;\r
+using System.ComponentModel;\r
+using System.Drawing.Imaging;\r
+using System.Drawing.Drawing2D;\r
+using System.Collections.Generic;\r
+using Myriadbits.MXF;\r
+using MaestroShared.Metadata;\r
+using NLog;\r
+\r
+namespace DxPlay {\r
+\r
+    internal class DxPlayerx : ISampleGrabberCB, IDisposable {\r
+        private static readonly Logger logger = LogManager.GetCurrentClassLogger();\r
+\r
+        [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory")]\r
+        private static extern void CopyMemory(IntPtr Destination, IntPtr Source, [MarshalAs(UnmanagedType.U4)] uint Length);\r
+\r
+        private const int MEDIATIME_REFERENCE = 10000000;\r
+\r
+        public enum GraphState {\r
+            Stopped,\r
+            Completed,\r
+            Paused,\r
+            Playing,\r
+            Exiting\r
+        }\r
+\r
+        public Dictionary<GraphState, string> stateHunStringValues = new Dictionary<GraphState, string>();\r
+\r
+        public MediaDescription MediaDescription { get; internal set; }\r
+        public Timecode CurrentTC { get; internal set; }\r
+        public GraphState State { get; internal set; }\r
+\r
+        private IFilterGraph2 m_FilterGraph;\r
+        private IMediaControl m_mediaCtrl;\r
+        private IMediaEvent m_mediaEvent;\r
+\r
+        // Event used by Media Event thread\r
+        private ManualResetEvent m_mre;\r
+        private BackgroundWorker tcWorker;\r
+        // Current state of the graph (can change async)\r
+\r
+        public event DxPlayEvent PlayEvent;\r
+        public delegate void DxPlayEvent();\r
+\r
+        private Thread m_eventThread = null;\r
+        private IMediaSeeking m_mediaSeek = null;\r
+\r
+        private IVideoWindow m_videoWindow = null;\r
+        private IBaseFilter m_videoRenderer = null;\r
+        private object tcLock = new object();\r
+        Bitmap m_Bitmap = null;\r
+        public bool IsError { get; set; }\r
+#if DEBUG\r
+        // Allow you to "Connect to remote graph" from GraphEdit\r
+        DsROTEntry m_DsRot;\r
+#endif\r
+        private int m_stride;\r
+\r
+        // Release everything.\r
+        public void Dispose() {\r
+            CloseInterfaces();\r
+        }\r
+\r
+        ~DxPlayerx() {\r
+            CloseInterfaces();\r
+        }\r
+\r
+        Control playerWindow;\r
+        private object ppUnk;\r
+\r
+        // Play an avi file into a window.  Allow for snapshots.\r
+        // (Control to show video in, Avi file to play\r
+        public DxPlayerx(Control hWin, ref MediaDescription mediaDesc) {\r
+            FillTheHunStringvalues();\r
+            State = GraphState.Stopped;\r
+            try {\r
+                int hr;\r
+                IntPtr hEvent;\r
+                MediaDescription = mediaDesc;\r
+                // Set up the graph\r
+                playerWindow = hWin;\r
+\r
+                SetupGraph();\r
+\r
+                hWin.Hide();\r
+                hWin.Show();\r
+\r
+                // Get the event handle the graph will use to signal\r
+                // when events occur\r
+                Debug.WriteLine("GetEventHandle");\r
+                hr = m_mediaEvent.GetEventHandle(out hEvent);\r
+                DsError.ThrowExceptionForHR(hr);\r
+\r
+                // Wrap the graph event with a ManualResetEvent\r
+                m_mre = new ManualResetEvent(false);\r
+                m_mre.SafeWaitHandle = new SafeWaitHandle(hEvent, true);\r
+\r
+                // Create a new thread to wait for events\r
+                Debug.WriteLine("m_eventThread.Start()");\r
+                m_eventThread = new Thread(new ThreadStart(EventWait));\r
+                m_eventThread.Name = "Media Event Thread";\r
+                m_eventThread.Start();\r
+\r
+                m_Bitmap = Properties.Resources.lgs;\r
+\r
+                tcWorker = new BackgroundWorker();\r
+                tcWorker.DoWork += TcWorker_DoWork;\r
+                tcWorker.WorkerSupportsCancellation = true;\r
+                tcWorker.RunWorkerAsync(tcLock);\r
+\r
+            }\r
+            catch {\r
+                Dispose();\r
+                throw;\r
+            }\r
+        }\r
+\r
+        private void FillTheHunStringvalues() {\r
+            stateHunStringValues.Add(GraphState.Exiting, StringResource.KILEPES);\r
+            stateHunStringValues.Add(GraphState.Paused, StringResource.SZUNETELTETETT);\r
+            stateHunStringValues.Add(GraphState.Playing, StringResource.LEJATSZAS);\r
+            stateHunStringValues.Add(GraphState.Stopped, StringResource.MEGALLITVA);\r
+            stateHunStringValues.Add(GraphState.Completed, StringResource.VEGE);\r
+        }\r
+\r
+        private void TcWorker_DoWork(object sender, DoWorkEventArgs e) {\r
+            while (!e.Cancel) {\r
+                UpdateTC();\r
+                Thread.Sleep(10);\r
+            }\r
+        }\r
+\r
+\r
+        // start playing\r
+        public void Play() {\r
+            // If we aren't already playing (or shutting down)\r
+            if (State == GraphState.Completed)\r
+                Stop();\r
+            if (State == GraphState.Stopped || State == GraphState.Paused) {\r
+                int hr = m_mediaCtrl.Run();\r
+                DsError.ThrowExceptionForHR(hr);\r
+\r
+                State = GraphState.Playing;\r
+            }\r
+        }\r
+\r
+        // Pause the capture graph.\r
+        public void Pause() {\r
+            // If we are playing\r
+            if (State == GraphState.Playing) {\r
+                int hr = m_mediaCtrl.Pause();\r
+                DsError.ThrowExceptionForHR(hr);\r
+\r
+                State = GraphState.Paused;\r
+                Seek(CurrentTC.ZeroBasedFrames);\r
+            }\r
+        }\r
+\r
+        // Pause the capture graph.\r
+        public void Stop() {\r
+            // Can only Stop when playing or paused\r
+            if (State == GraphState.Playing || State == GraphState.Paused || State == GraphState.Completed) {\r
+                int hr = m_mediaCtrl.Stop();\r
+                DsError.ThrowExceptionForHR(hr);\r
+                State = GraphState.Stopped;\r
+            }\r
+            Rewind();\r
+            PlayEvent?.Invoke();\r
+        }\r
+\r
+        // Reset the clip back to the beginning\r
+        public void Rewind() {\r
+            Seek(0);\r
+        }\r
+\r
+        public void Seek(int value) {\r
+            double frameLength = (double)MEDIATIME_REFERENCE / MediaDescription.FrameRate;\r
+            long avgTimePerFrame = (long)Math.Ceiling(MEDIATIME_REFERENCE / MediaDescription.FrameRate);\r
+            long requestedPosition = (long)Math.Ceiling(value * frameLength);\r
+            int hr = m_mediaSeek.SetPositions(requestedPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);\r
+            DsError.ThrowExceptionForHR(hr);\r
+\r
+            long currentPosition;\r
+            hr = m_mediaSeek.GetCurrentPosition(out currentPosition);\r
+            DsError.ThrowExceptionForHR(hr);\r
+            bool corrected = false;\r
+            int reachedFrames = (int)Math.Abs((double)currentPosition / avgTimePerFrame);\r
+            if (reachedFrames != value) {\r
+                //NTSC-n nem megy a seek a kerekítési hibák miatt, mindíg ua. a frame jön ki     \r
+                requestedPosition += (int)frameLength / 2;\r
+                hr = m_mediaSeek.SetPositions(requestedPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);\r
+                DsError.ThrowExceptionForHR(hr);\r
+                corrected = true;\r
+            }\r
+\r
+            Debug.WriteLine("Seeking requested frame {0} got frame {1}, media position {2}, frame length {3}, corrected {4}", value, reachedFrames, requestedPosition, avgTimePerFrame, corrected);\r
+        }\r
+\r
+        private void UpdateTC() {\r
+            if (m_mediaSeek == null)\r
+                return;\r
+            long currentPosition;\r
+            int hr = m_mediaSeek.GetCurrentPosition(out currentPosition);\r
+            DsError.ThrowExceptionForHR(hr);\r
+            int frames = ReferenceTimeToFrames(currentPosition);\r
+            if (CurrentTC.ZeroBasedFrames != frames) {\r
+                CurrentTC.Set(frames);\r
+                //Debug.WriteLine("Current frame is {0} ({1}), media position is {2}, AVG frame time is {3}", frames, CurrentTC.ToString(), currentPosition, AvgTimePerFrame);\r
+            }\r
+            PlayEvent?.Invoke();\r
+\r
+        }\r
+\r
+        private int ReferenceTimeToFrames(long refTime) {\r
+            long AvgTimePerFrame = (long)Math.Ceiling(MEDIATIME_REFERENCE / MediaDescription.FrameRate);\r
+            return (int)Math.Abs((double)refTime / AvgTimePerFrame);\r
+        }\r
+\r
+        private void SetupGraph() {\r
+            int hr;\r
+\r
+            try {\r
+                IsError = false;\r
+                m_FilterGraph = new FilterGraph() as IFilterGraph2;\r
+\r
+                IGraphBuilder graphBuilder = m_FilterGraph as IGraphBuilder;\r
+                m_mediaSeek = m_FilterGraph as IMediaSeeking;\r
+                m_mediaEvent = m_FilterGraph as IMediaEvent;\r
+                m_mediaCtrl = m_FilterGraph as IMediaControl;\r
+                m_videoWindow = m_FilterGraph as IVideoWindow;\r
+\r
+#if DEBUG\r
+                m_DsRot = new DsROTEntry(m_FilterGraph);\r
+#endif\r
+                logger.Debug("Add SourceFilter to graph");\r
+                IBaseFilter sourceFilter = null;\r
+                hr = m_FilterGraph.AddSourceFilter(MediaDescription.FileName, MediaDescription.FileName, out sourceFilter);\r
+                DsError.ThrowExceptionForHR(hr);\r
+\r
+                //Type typeFromClsid = Type.GetTypeFromCLSID(new Guid("CCE7BD95-3BC4-4cfb-9664-0BF83201BE09"));\r
+                //splitter = (IBaseFilter)Activator.CreateInstance(typeFromClsid);\r
+                //m_FilterGraph.AddFilter(splitter, "MXF Splitter");\r
+                //splitter = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "Sony MXF Splitter");\r
+\r
+                logger.Debug("Add LAVSplitter to graph");\r
+                IBaseFilter splitter = LoadSplitter(graphBuilder);\r
+                if (splitter == null)\r
+                    throw new Exception("No splitter!");\r
+\r
+                logger.Debug("Connect SourceFilter -> LAVSplitter");\r
+                FilterGraphTools.ConnectFilters(graphBuilder, sourceFilter, "Output", splitter, "Input", true);\r
+\r
+                IAMStreamSelect amStreamSelect = (IAMStreamSelect)splitter;\r
+                if (amStreamSelect != null) {\r
+                    int count = 0;\r
+                    amStreamSelect.Count(out count);\r
+                    int audioCount = 0;\r
+                    for (int i = 0; i < count; i++) {\r
+                        AMMediaType ppmt;\r
+                        AMStreamSelectInfoFlags pdwFlags;\r
+                        int plcid;\r
+                        int pdwGroup;\r
+                        string ppszName;\r
+                        object ppObject;\r
+                        amStreamSelect.Info(i, out ppmt, out pdwFlags, out plcid, out pdwGroup, out ppszName, out ppObject, out ppUnk);\r
+\r
+                        if (ppmt.majorType == MediaType.Audio) {\r
+                            Debug.WriteLine("Found audio channel");\r
+                            audioCount++;\r
+                        }\r
+\r
+                        DsUtils.FreeAMMediaType(ppmt);\r
+                        //Marshal.FreeCoTaskMem(ppszName);\r
+                        if (ppObject != null)\r
+                            DsUtils.ReleaseComObject(ppUnk);\r
+\r
+                    }\r
+                    Debug.WriteLine("Audio count: " + audioCount);\r
+                }\r
+\r
+                logger.Debug("Add LAVVideo to graph");\r
+                IBaseFilter videoDecoder = LoadVideoDecoder(graphBuilder);\r
+\r
+                if (videoDecoder == null)\r
+                    throw new Exception("No video decoder!");\r
+\r
+                logger.Debug("Connect LAVSplitter -> LAVVideo");\r
+                FilterGraphTools.ConnectFilters(graphBuilder, splitter, "Video", videoDecoder, "Input", true);\r
+\r
+                logger.Debug("Add SampleGrabber to graph");\r
+                IBaseFilter sampGrabber = (IBaseFilter)new SampleGrabber();\r
+                ISampleGrabber sampleGrabber = (ISampleGrabber)sampGrabber;\r
+                ConfigureSampleGrabber(sampleGrabber);\r
+\r
+                hr = m_FilterGraph.AddFilter(sampGrabber, "Sample Grabber");\r
+                DsError.ThrowExceptionForHR(hr);\r
+\r
+                logger.Debug("Connect LAVVideo -> SampleGrabber");\r
+                FilterGraphTools.ConnectFilters(graphBuilder, videoDecoder, "Output", sampGrabber, "Input", true);\r
+\r
+                AMMediaType media = new AMMediaType();\r
+                sampleGrabber.GetConnectedMediaType(media);\r
+                logger.Debug("SaveSizeInfo");\r
+                SaveSizeInfo(media);\r
+                DsUtils.FreeAMMediaType(media);\r
+\r
+                logger.Debug("Add VideoMixingRenderer9 to graph");\r
+                m_videoRenderer = (IBaseFilter)new VideoMixingRenderer9();\r
+                hr = m_FilterGraph.AddFilter(m_videoRenderer, "Video Mixing Renderer 9");\r
+                DsError.ThrowExceptionForHR(hr);\r
+\r
+\r
+                try {\r
+                    //IPin pin = DsFindPin.ByName(sampGrabber, "Output");\r
+                    //m_FilterGraph.RenderEx(pin, AMRenderExFlags.RenderToExistingRenderers, IntPtr.Zero);\r
+                    //Marshal.ReleaseComObject(pin);\r
+                    logger.Debug("Connect SampleGrabber -> VideoMixingRenderer9");\r
+                    FilterGraphTools.ConnectFilters(graphBuilder, sampGrabber, "Output", m_videoRenderer, "VMR Input0", true);\r
+                }\r
+                catch (Exception e) {\r
+                    logger.Error(e);\r
+                }\r
+\r
+                try {\r
+                    if (DsFindPin.ByName(splitter, "Audio") != null) {\r
+                        logger.Debug("Add LAVAudio to graph");\r
+                        IBaseFilter audioDecoder = null;\r
+                        audioDecoder = LoadAudioDecoder(graphBuilder);\r
+                        if (audioDecoder == null)\r
+                            throw new Exception("No audio decoder!");\r
+\r
+                        logger.Debug("Connect LAVSplitter -> LAVAudio");\r
+                        FilterGraphTools.ConnectFilters(graphBuilder, splitter, "Audio", audioDecoder, "Input", true);\r
+                        FilterGraphTools.RenderPin(graphBuilder, audioDecoder, "Output");\r
+                    } else {\r
+                        logger.Warn("Audio pin not available");\r
+                    }\r
+                }\r
+                catch (Exception ex) {\r
+                    logger.Warn("Audio pin not available");\r
+                }\r
+\r
+\r
+                //logger.Debug("SaveSizeInfo");\r
+                //SaveSizeInfo(sampGrabber as ISampleGrabber);\r
+                logger.Debug("SetTimeCodes");\r
+                SetTimeCodes();\r
+                logger.Debug("ConfigureVideoWindow");\r
+                ConfigureVideoWindow();\r
+\r
+                logger.Debug("Enable YADIF deinterlace");\r
+                ILAVVideoSettings settings = (ILAVVideoSettings)videoDecoder;\r
+                settings.SetSWDeintMode(LAVSWDeintModes.SWDeintMode_YADIF);\r
+                settings.SetSWDeintOutput(LAVDeintOutput.DeintOutput_FramePer2Field);\r
+            }\r
+            catch (Exception e) {\r
+                Debug.WriteLine(e.Message);\r
+                IsError = true;\r
+            }\r
+            finally {\r
+            }\r
+#if DEBUG\r
+            // Double check to make sure we aren't releasing something\r
+            // important.\r
+            //GC.Collect();\r
+            //GC.WaitForPendingFinalizers();\r
+#endif\r
+        }\r
+\r
+        private static IBaseFilter LoadVideoDecoder(IGraphBuilder graphBuilder) {\r
+            IBaseFilter videoDecoder = null;\r
+            ILAVVideoSettings lavVideoSettings;\r
+            videoDecoder = FilterProvider.GetVideoFilter(out lavVideoSettings);\r
+            if (videoDecoder == null)\r
+                videoDecoder = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Video Decoder");\r
+            else\r
+                graphBuilder.AddFilter(videoDecoder, "LAV Video Decoder");\r
+            return videoDecoder;\r
+        }\r
+\r
+        private static IBaseFilter LoadAudioDecoder(IGraphBuilder graphBuilder) {\r
+            IBaseFilter audioDecoder = null;\r
+            ILAVAudioSettings lavAudioSettings;\r
+            ILAVAudioStatus lavAudioStatus;\r
+            audioDecoder = FilterProvider.GetAudioFilter(out lavAudioSettings, out lavAudioStatus);\r
+            if (audioDecoder == null)\r
+                audioDecoder = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Audio Decoder");\r
+            else\r
+                graphBuilder.AddFilter(audioDecoder, "LAV Audio Decoder");\r
+            return audioDecoder;\r
+        }\r
+\r
+        private static IBaseFilter LoadSplitter(IGraphBuilder graphBuilder) {\r
+            IBaseFilter splitter = null;\r
+            ILAVSplitterSettings lavSplitterSettings;\r
+            splitter = FilterProvider.GetSplitter(out lavSplitterSettings);\r
+            if (splitter == null)\r
+                splitter = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Splitter");\r
+            else\r
+                graphBuilder.AddFilter(splitter, "LAV Splitter");\r
+            return splitter;\r
+        }\r
+\r
+        private void SetTimeCodes() {\r
+            int hr;\r
+            long duration;\r
+            hr = m_mediaSeek.GetDuration(out duration);\r
+            DsError.ThrowExceptionForHR(hr);\r
+            MediaDescription.duration = new Timecode();\r
+            MediaDescription.Duration.Set(ReferenceTimeToFrames(duration));\r
+            if (MediaDescription.FirstFrame == null) {\r
+                try {\r
+                    MXFFile mxf = new MXFFile(MediaDescription.FileName);\r
+                    mxf.Inspect();\r
+                    //MediaDescription.firstFrame = new Timecode(mxf.FirstSystemItem?.UserDateFullFrameNb, MediaDescription.FrameRate);\r
+                    MediaDescription.firstFrame = new Timecode((int)mxf.TimecodeComponent.StartTimecode, (float)mxf.TimecodeComponent.RoundedTimecodeBase);\r
+                }\r
+                catch (Exception ex) {\r
+                    MediaDescription.firstFrame = new Timecode();\r
+                }\r
+            }\r
+            //MediaDescription.firstFrame = new Timecode();\r
+            CurrentTC = new Timecode(MediaDescription.FirstFrame);\r
+        }\r
+\r
+\r
+        // Configure the video window\r
+        private void ConfigureVideoWindow() {\r
+            int hr;\r
+\r
+            // Set the output window\r
+            hr = m_videoWindow.put_Owner(playerWindow.Handle);\r
+            DsError.ThrowExceptionForHR(hr);\r
+\r
+            hr = m_videoWindow.put_MessageDrain(playerWindow.Handle);\r
+            DsError.ThrowExceptionForHR(hr);\r
+\r
+            // Set the window style\r
+            hr = m_videoWindow.put_WindowStyle((WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings));\r
+            DsError.ThrowExceptionForHR(hr);\r
+\r
+            // Make the window visible\r
+            hr = m_videoWindow.put_Visible(OABool.True);\r
+            DsError.ThrowExceptionForHR(hr);\r
+\r
+            UpdateVideoWindow();\r
+        }\r
+\r
+        public void UpdateVideoWindow() {\r
+            Size resolution = MediaDescription.Resolution;\r
+            if (resolution.Width == 0 || resolution.Height == 0)\r
+                return;\r
+            int hr;\r
+            // Position the playing location\r
+            Rectangle rc = playerWindow.ClientRectangle;\r
+            double x = (double)resolution.Width / resolution.Height;\r
+            double y = (double)rc.Right / rc.Bottom;\r
+            int playerWidth = 0;\r
+            int playerHeight = 0;\r
+            if (x - y < 0) {\r
+                playerWidth = (int)Math.Ceiling(rc.Bottom * x);\r
+                playerHeight = rc.Bottom;\r
+            } else {\r
+                x = (double)resolution.Height / resolution.Width;\r
+                playerWidth = rc.Right;\r
+                playerHeight = (int)Math.Ceiling(rc.Right * x); ;\r
+            }\r
+\r
+            hr = m_videoWindow.SetWindowPosition((rc.Right - playerWidth) / 2, (rc.Bottom - playerHeight) / 2, playerWidth, playerHeight);\r
+            DsError.ThrowExceptionForHR(hr);\r
+        }\r
+\r
+        public void ToggleFullscreen() {\r
+            m_videoWindow.put_FullScreenMode(IsFullscreen() ? OABool.False : OABool.True);\r
+        }\r
+\r
+        public bool IsFullscreen() {\r
+            OABool isFullscreen;\r
+            int hr = m_videoWindow.get_FullScreenMode(out isFullscreen);\r
+            DsError.ThrowExceptionForHR(hr);\r
+            return isFullscreen == OABool.True ? true : false;\r
+        }\r
+\r
+        // Set the options on the sample grabber\r
+        private void ConfigureSampleGrabber(ISampleGrabber sampGrabber) {\r
+            int hr;\r
+            //AMMediaType media;\r
+            //media = new AMMediaType();\r
+            //media.majorType = MediaType.Video;\r
+            //media.subType = MediaSubType.RGB24;\r
+            //media.formatType = FormatType.VideoInfo;\r
+            //hr = sampGrabber.SetMediaType(media);\r
+            //DsError.ThrowExceptionForHR(hr);\r
+            //DsUtils.FreeAMMediaType(media);\r
+\r
+            hr = sampGrabber.SetCallback(this, 1);\r
+            DsError.ThrowExceptionForHR(hr);\r
+\r
+            // Configure the samplegrabber\r
+            hr = sampGrabber.SetBufferSamples(true);\r
+            DsError.ThrowExceptionForHR(hr);\r
+        }\r
+\r
+        private void SaveSizeInfo(AMMediaType media) {\r
+            //int hr;\r
+            //AMMediaType media = new AMMediaType();\r
+            //hr = sampGrabber.GetConnectedMediaType(media);\r
+            //DsError.ThrowExceptionForHR(hr);\r
+\r
+            if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero)) {\r
+                throw new NotSupportedException("Unknown Grabber Media Format");\r
+            }\r
+\r
+            // Grab the size info\r
+            VideoInfoHeader videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));\r
+            MediaDescription.resolution = new Size(videoInfoHeader.BmiHeader.Width, videoInfoHeader.BmiHeader.Height);\r
+            MediaDescription.frameRate = MEDIATIME_REFERENCE / videoInfoHeader.AvgTimePerFrame;\r
+\r
+            m_stride = videoInfoHeader.BmiHeader.Width * (videoInfoHeader.BmiHeader.BitCount / 8);\r
+        }\r
+\r
+        // Shut down capture\r
+        private void CloseInterfaces() {\r
+            Debug.WriteLine("CloseInterfaces");\r
+            int hr;\r
+            GC.SuppressFinalize(this);\r
+            if (tcWorker != null)\r
+                tcWorker.CancelAsync();\r
+            lock (this) {\r
+                if (State != GraphState.Exiting) {\r
+                    State = GraphState.Exiting;\r
+\r
+                    // Release the thread (if the thread was started)\r
+                    if (m_mre != null) {\r
+                        m_mre.Set();\r
+                    }\r
+                }\r
+\r
+                if (m_mediaCtrl != null) {\r
+                    // Stop the graph\r
+                    hr = m_mediaCtrl.Stop();\r
+                    FilterGraphTools.DisconnectAllPins((IGraphBuilder)m_mediaCtrl);\r
+                    FilterGraphTools.RemoveAllFilters((IGraphBuilder)m_mediaCtrl);\r
+                    m_mediaCtrl = null;\r
+\r
+                }\r
+\r
+                if (m_videoWindow != null) {\r
+                    hr = m_videoWindow.put_Visible(OABool.False);\r
+                    hr = m_videoWindow.put_MessageDrain(IntPtr.Zero);\r
+                    hr = m_videoWindow.put_Owner(IntPtr.Zero);\r
+                    m_videoWindow = null;\r
+                }\r
+\r
+                m_mediaEvent = null;\r
+                m_mediaSeek = null;\r
+\r
+#if DEBUG\r
+                if (m_DsRot != null) {\r
+                    m_DsRot.Dispose();\r
+                    m_DsRot = null;\r
+                }\r
+#endif\r
+                if (m_FilterGraph != null) {\r
+                    Marshal.ReleaseComObject(m_FilterGraph);\r
+                    m_FilterGraph = null;\r
+                }\r
+            }\r
+            GC.Collect();\r
+            //if (m_eventThread != null)\r
+            //    m_eventThread.Join();\r
+        }\r
+\r
+        public int SampleCB(double SampleTime, IMediaSample pSample) {\r
+            Marshal.ReleaseComObject(pSample);\r
+            return 0;\r
+        }\r
+\r
+        public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen) {\r
+            return 0;\r
+            int frames = (int)Math.Abs(SampleTime * MediaDescription.FrameRate);\r
+            //Debug.WriteLine("BufferCB frames {0}, sample time {1}", frames, SampleTime);\r
+            Font font = new Font("Tahoma", 30);\r
+            string display = frames.ToString();\r
+            SizeF size = new SizeF(100, 100);\r
+            m_Bitmap = new Bitmap((int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height));\r
+            GraphicsUnit units = GraphicsUnit.Point;\r
+            RectangleF bitmapRectF = m_Bitmap.GetBounds(ref units);\r
+\r
+            Graphics g = Graphics.FromImage(m_Bitmap);\r
+\r
+            g.SmoothingMode = SmoothingMode.AntiAlias;\r
+            g.InterpolationMode = InterpolationMode.HighQualityBicubic;\r
+            g.PixelOffsetMode = PixelOffsetMode.HighQuality;\r
+            g.FillRectangle(Brushes.Transparent, bitmapRectF);\r
+            g.DrawString(display, font, Brushes.White, bitmapRectF);\r
+            g.Flush();\r
+\r
+            m_Bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);\r
+            Rectangle r = new Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height);\r
+            lock (this) {\r
+                BitmapData bmdLogo = m_Bitmap.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);\r
+                if (bmdLogo != null) {\r
+                    IntPtr ipSource = bmdLogo.Scan0;\r
+                    IntPtr ipDest = pBuffer;\r
+\r
+                    for (int x = 0; x < bmdLogo.Height; x++) {\r
+                        CopyMemory(ipDest, ipSource, (uint)bmdLogo.Stride);\r
+                        ipDest = (IntPtr)(ipDest.ToInt64() + m_stride);\r
+                        ipSource = (IntPtr)(ipSource.ToInt64() + bmdLogo.Stride);\r
+                    }\r
+                }\r
+                m_Bitmap.UnlockBits(bmdLogo);\r
+                bmdLogo = null;\r
+            }\r
+            return 0;\r
+        }\r
+\r
+        // Wait for events to happen.  This approach uses waiting on an event handle.\r
+        // The nice thing about doing it this way is that you aren't in the windows message\r
+        // loop, and don't have to worry about re-entrency or taking too long.  Plus, being\r
+        // in a class as we are, we don't have access to the message loop.\r
+        // Alternately, you can receive your events as windows messages.  See\r
+        // IMediaEventEx.SetNotifyWindow.\r
+        private void EventWait() {\r
+            // Returned when GetEvent is called but there are no events\r
+            const int E_ABORT = unchecked((int)0x80004004);\r
+\r
+            int hr;\r
+            IntPtr p1, p2;\r
+            EventCode ec;\r
+\r
+            do {\r
+                // Wait for an event\r
+                m_mre.WaitOne(-1, true);\r
+\r
+                // Avoid contention for m_State\r
+                lock (this) {\r
+                    // If we are not shutting down\r
+                    if (State != GraphState.Exiting) {\r
+                        // Read the event\r
+                        for (\r
+                            hr = m_mediaEvent.GetEvent(out ec, out p1, out p2, 0);\r
+                            hr >= 0;\r
+                            hr = m_mediaEvent.GetEvent(out ec, out p1, out p2, 0)\r
+                            ) {\r
+                            // Write the event name to the debug window\r
+                            Debug.WriteLine(ec.ToString());\r
+\r
+                            // If the clip is finished playing\r
+                            if (ec == EventCode.Complete) {\r
+                                State = GraphState.Completed;\r
+                            }\r
+\r
+                            // Release any resources the message allocated\r
+                            hr = m_mediaEvent.FreeEventParams(ec, p1, p2);\r
+                            DsError.ThrowExceptionForHR(hr);\r
+\r
+                            //lock (tcLock) {\r
+                            //    UpdateTC("");\r
+                            //}\r
+\r
+                        }\r
+\r
+                        // If the error that exited the loop wasn't due to running out of events\r
+                        if (hr != E_ABORT) {\r
+                            DsError.ThrowExceptionForHR(hr);\r
+                        }\r
+                    } else {\r
+                        // We are shutting down\r
+                        Debug.WriteLine("Shutdown");\r
+                        break;\r
+                    }\r
+                }\r
+            } while (true);\r
+        }\r
+\r
+    }\r
+}\r
index 9cbe9d8e837a0a48c1128abfc994d4130881fb05..061994fcfd948f02350e578ce1f0a386238ca518 100644 (file)
@@ -6,7 +6,6 @@ using System.Windows.Forms;
 using System.Threading;\r
 \r
 using DirectShowLib;\r
-using DirectShowLib.Utils;\r
 using Microsoft.Win32.SafeHandles;\r
 using System.ComponentModel;\r
 using System.Drawing.Imaging;\r
@@ -35,39 +34,19 @@ namespace DxPlay {
         }\r
 \r
         public Dictionary<GraphState, string> stateHunStringValues = new Dictionary<GraphState, string>();\r
-\r
         public MediaDescription MediaDescription { get; internal set; }\r
         public Timecode CurrentTC { get; internal set; }\r
         public GraphState State { get; internal set; }\r
-\r
-        private IFilterGraph2 m_FilterGraph;\r
-        private IMediaControl m_mediaCtrl;\r
-        private IMediaEvent m_mediaEvent;\r
-\r
-        // Event used by Media Event thread\r
         private ManualResetEvent m_mre;\r
         private BackgroundWorker tcWorker;\r
-        // Current state of the graph (can change async)\r
-\r
         public event DxPlayEvent PlayEvent;\r
         public delegate void DxPlayEvent();\r
-\r
         private Thread m_eventThread = null;\r
-        private IMediaSeeking m_mediaSeek = null;\r
-        private IMediaPosition m_mediaPosition = null;\r
-\r
-        private IVideoWindow m_videoWindow = null;\r
-        private IBaseFilter m_videoRenderer = null;\r
         private object tcLock = new object();\r
         Bitmap m_Bitmap = null;\r
         public bool IsError { get; set; }\r
-#if DEBUG\r
-        // Allow you to "Connect to remote graph" from GraphEdit\r
-        DsROTEntry m_DsRot;\r
-#endif\r
         private int m_stride;\r
 \r
-        // Release everything.\r
         public void Dispose() {\r
             CloseInterfaces();\r
         }\r
@@ -78,6 +57,7 @@ namespace DxPlay {
 \r
         Control playerWindow;\r
         private object ppUnk;\r
+        private PlayerGraph graph;\r
 \r
         // Play an avi file into a window.  Allow for snapshots.\r
         // (Control to show video in, Avi file to play\r
@@ -99,7 +79,7 @@ namespace DxPlay {
                 // Get the event handle the graph will use to signal\r
                 // when events occur\r
                 Debug.WriteLine("GetEventHandle");\r
-                hr = m_mediaEvent.GetEventHandle(out hEvent);\r
+                hr = graph.MediaEvent.GetEventHandle(out hEvent);\r
                 DsError.ThrowExceptionForHR(hr);\r
 \r
                 // Wrap the graph event with a ManualResetEvent\r
@@ -126,6 +106,23 @@ namespace DxPlay {
             }\r
         }\r
 \r
+        private void SetupGraph() {\r
+            graph = new PlayerGraph(MediaDescription.FileName);\r
+\r
+            AMMediaType media = new AMMediaType();\r
+            graph.SampleGrabber.GetConnectedMediaType(media);\r
+            logger.Debug("SaveSizeInfo");\r
+            SaveSizeInfo(media);\r
+            DsUtils.FreeAMMediaType(media);\r
+\r
+            logger.Debug("ConfigureSampleGrabber");\r
+            ConfigureSampleGrabber(graph.SampleGrabber);\r
+            logger.Debug("SetTimeCodes");\r
+            SetTimeCodes();\r
+            logger.Debug("ConfigureVideoWindow");\r
+            ConfigureVideoWindow();\r
+        }\r
+\r
         private void FillTheHunStringvalues() {\r
             stateHunStringValues.Add(GraphState.Exiting, StringResource.KILEPES);\r
             stateHunStringValues.Add(GraphState.Paused, StringResource.SZUNETELTETETT);\r
@@ -148,7 +145,7 @@ namespace DxPlay {
             if (State == GraphState.Completed)\r
                 Stop();\r
             if (State == GraphState.Stopped || State == GraphState.Paused) {\r
-                int hr = m_mediaCtrl.Run();\r
+                int hr = graph.MediaControl.Run();\r
                 DsError.ThrowExceptionForHR(hr);\r
 \r
                 State = GraphState.Playing;\r
@@ -159,7 +156,7 @@ namespace DxPlay {
         public void Pause() {\r
             // If we are playing\r
             if (State == GraphState.Playing) {\r
-                int hr = m_mediaCtrl.Pause();\r
+                int hr = graph.MediaControl.Pause();\r
                 DsError.ThrowExceptionForHR(hr);\r
 \r
                 State = GraphState.Paused;\r
@@ -171,7 +168,7 @@ namespace DxPlay {
         public void Stop() {\r
             // Can only Stop when playing or paused\r
             if (State == GraphState.Playing || State == GraphState.Paused || State == GraphState.Completed) {\r
-                int hr = m_mediaCtrl.Stop();\r
+                int hr = graph.MediaControl.Stop();\r
                 DsError.ThrowExceptionForHR(hr);\r
                 State = GraphState.Stopped;\r
             }\r
@@ -185,21 +182,24 @@ namespace DxPlay {
         }\r
 \r
         public void Seek(int value) {\r
+            if (graph == null || graph.MediaSeeking == null)\r
+                return;\r
+\r
             double frameLength = (double)MEDIATIME_REFERENCE / MediaDescription.FrameRate;\r
             long avgTimePerFrame = (long)Math.Ceiling(MEDIATIME_REFERENCE / MediaDescription.FrameRate);\r
             long requestedPosition = (long)Math.Ceiling(value * frameLength);\r
-            int hr = m_mediaSeek.SetPositions(requestedPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);\r
+            int hr = graph.MediaSeeking.SetPositions(requestedPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);\r
             DsError.ThrowExceptionForHR(hr);\r
 \r
             long currentPosition;\r
-            hr = m_mediaSeek.GetCurrentPosition(out currentPosition);\r
+            hr = graph.MediaSeeking.GetCurrentPosition(out currentPosition);\r
             DsError.ThrowExceptionForHR(hr);\r
             bool corrected = false;\r
             int reachedFrames = (int)Math.Abs((double)currentPosition / avgTimePerFrame);\r
             if (reachedFrames != value) {\r
                 //NTSC-n nem megy a seek a kerekítési hibák miatt, mindíg ua. a frame jön ki     \r
                 requestedPosition += (int)frameLength / 2;\r
-                hr = m_mediaSeek.SetPositions(requestedPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);\r
+                hr = graph.MediaSeeking.SetPositions(requestedPosition, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning);\r
                 DsError.ThrowExceptionForHR(hr);\r
                 corrected = true;\r
             }\r
@@ -208,10 +208,10 @@ namespace DxPlay {
         }\r
 \r
         private void UpdateTC() {\r
-            if (m_mediaSeek == null)\r
+            if (graph == null || graph.MediaSeeking == null)\r
                 return;\r
             long currentPosition;\r
-            int hr = m_mediaSeek.GetCurrentPosition(out currentPosition);\r
+            int hr = graph.MediaSeeking.GetCurrentPosition(out currentPosition);\r
             DsError.ThrowExceptionForHR(hr);\r
             int frames = ReferenceTimeToFrames(currentPosition);\r
             if (CurrentTC.ZeroBasedFrames != frames) {\r
@@ -227,189 +227,10 @@ namespace DxPlay {
             return (int)Math.Abs((double)refTime / AvgTimePerFrame);\r
         }\r
 \r
-        private void SetupGraph() {\r
-            int hr;\r
-\r
-            try {\r
-                IsError = false;\r
-                m_FilterGraph = new FilterGraph() as IFilterGraph2;\r
-\r
-                IGraphBuilder graphBuilder = m_FilterGraph as IGraphBuilder;\r
-                m_mediaSeek = m_FilterGraph as IMediaSeeking;\r
-                m_mediaPosition = m_FilterGraph as IMediaPosition;\r
-                m_mediaEvent = m_FilterGraph as IMediaEvent;\r
-                m_mediaCtrl = m_FilterGraph as IMediaControl;\r
-                m_videoWindow = m_FilterGraph as IVideoWindow;\r
-\r
-#if DEBUG\r
-                m_DsRot = new DsROTEntry(m_FilterGraph);\r
-#endif\r
-                logger.Debug("Add SourceFilter to graph");\r
-                IBaseFilter sourceFilter = null;\r
-                hr = m_FilterGraph.AddSourceFilter(MediaDescription.FileName, MediaDescription.FileName, out sourceFilter);\r
-                DsError.ThrowExceptionForHR(hr);\r
-\r
-                //Type typeFromClsid = Type.GetTypeFromCLSID(new Guid("CCE7BD95-3BC4-4cfb-9664-0BF83201BE09"));\r
-                //splitter = (IBaseFilter)Activator.CreateInstance(typeFromClsid);\r
-                //m_FilterGraph.AddFilter(splitter, "MXF Splitter");\r
-                //splitter = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "Sony MXF Splitter");\r
-\r
-                logger.Debug("Add LAVSplitter to graph");\r
-                IBaseFilter splitter = LoadSplitter(graphBuilder);\r
-                if (splitter == null)\r
-                    throw new Exception("No splitter!");\r
-\r
-                logger.Debug("Connect SourceFilter -> LAVSplitter");\r
-                FilterGraphTools.ConnectFilters(graphBuilder, sourceFilter, "Output", splitter, "Input", true);\r
-\r
-                //IAMStreamSelect amStreamSelect = (IAMStreamSelect)splitter;\r
-                //if (amStreamSelect != null) {\r
-                //    int count = 0;\r
-                //    amStreamSelect.Count(out count);\r
-                //    int audioCount = 0;\r
-                //    for (int i = 0; i < count; i++) {\r
-                //        AMMediaType ppmt;\r
-                //        AMStreamSelectInfoFlags pdwFlags;\r
-                //        int plcid;\r
-                //        int pdwGroup;\r
-                //        string ppszName;\r
-                //        object ppObject;\r
-                //        amStreamSelect.Info(i, out ppmt, out pdwFlags, out plcid, out pdwGroup, out ppszName, out ppObject, out ppUnk);\r
-\r
-                //        if (ppmt.majorType == MediaType.Audio) {\r
-                //            Debug.WriteLine("Found audio channel");\r
-                //            audioCount++;\r
-                //        }\r
-\r
-                //        DsUtils.FreeAMMediaType(ppmt);\r
-                //        //Marshal.FreeCoTaskMem(ppszName);\r
-                //        if (ppObject != null)\r
-                //            DsUtils.ReleaseComObject(ppUnk);\r
-\r
-                //    }\r
-                //    Debug.WriteLine("Audio count: " + audioCount);\r
-                //}\r
-\r
-                logger.Debug("Add LAVVideo to graph");\r
-                IBaseFilter videoDecoder = LoadVideoDecoder(graphBuilder);\r
-\r
-                if (videoDecoder == null)\r
-                    throw new Exception("No video decoder!");\r
-\r
-                logger.Debug("Connect LAVSplitter -> LAVVideo");\r
-                FilterGraphTools.ConnectFilters(graphBuilder, splitter, "Video", videoDecoder, "Input", true);\r
-\r
-                logger.Debug("Add SampleGrabber to graph");\r
-                IBaseFilter sampGrabber = (IBaseFilter)new SampleGrabber();\r
-                ConfigureSampleGrabber((ISampleGrabber)sampGrabber);\r
-                hr = m_FilterGraph.AddFilter(sampGrabber, "Sample Grabber");\r
-                DsError.ThrowExceptionForHR(hr);\r
-\r
-                logger.Debug("Connect LAVVideo -> SampleGrabber");\r
-                FilterGraphTools.ConnectFilters(graphBuilder, videoDecoder, "Output", sampGrabber, "Input", true);\r
-\r
-                logger.Debug("Add VideoMixingRenderer9 to graph");\r
-                m_videoRenderer = (IBaseFilter)new VideoMixingRenderer9();\r
-                hr = m_FilterGraph.AddFilter(m_videoRenderer, "Video Mixing Renderer 9");\r
-                DsError.ThrowExceptionForHR(hr);\r
-\r
-                //logger.Debug("Add VideoMixingRenderer9 to graph");\r
-                //IVMRDeinterlaceControl9 deinterlace = (IVMRDeinterlaceControl9)m_videoRenderer;\r
-                //Guid interlaceMode;\r
-                //deinterlace.GetActualDeinterlaceMode(0, out interlaceMode);\r
-\r
-                try {\r
-                    logger.Debug("Connect SampleGrabber -> VideoMixingRenderer9");\r
-                    FilterGraphTools.ConnectFilters(graphBuilder, sampGrabber, "Output", m_videoRenderer, "VMR Input0", true);\r
-                }\r
-                catch (Exception e) {\r
-                    logger.Error(e);\r
-                }\r
-\r
-                try {\r
-                    if (DsFindPin.ByName(splitter, "Audio") != null) {\r
-                        logger.Debug("Add LAVAudio to graph");\r
-                        IBaseFilter audioDecoder = null;\r
-                        audioDecoder = LoadAudioDecoder(graphBuilder);\r
-                        if (audioDecoder == null)\r
-                            throw new Exception("No audio decoder!");\r
-\r
-                        logger.Debug("Connect LAVSplitter -> LAVAudio");\r
-                        FilterGraphTools.ConnectFilters(graphBuilder, splitter, "Audio", audioDecoder, "Input", true);\r
-                        FilterGraphTools.RenderPin(graphBuilder, audioDecoder, "Output");\r
-                    } else {\r
-                        logger.Warn("Audio pin not available");\r
-                    }\r
-                }\r
-                catch (Exception ex) {\r
-                    logger.Warn("Audio pin not available");\r
-                }\r
-\r
-                logger.Debug("SaveSizeInfo");\r
-                SaveSizeInfo(sampGrabber as ISampleGrabber);\r
-                logger.Debug("SetTimeCodes");\r
-                SetTimeCodes();\r
-                logger.Debug("ConfigureVideoWindow");\r
-                ConfigureVideoWindow();\r
-\r
-                logger.Debug("Enable YADIF deinterlace");\r
-                ILAVVideoSettings settings = (ILAVVideoSettings)videoDecoder;\r
-                //settings.SetSWDeintMode(LAVSWDeintModes.SWDeintMode_None);\r
-                settings.SetSWDeintMode(LAVSWDeintModes.SWDeintMode_YADIF);\r
-                settings.SetSWDeintOutput(LAVDeintOutput.DeintOutput_FramePer2Field);\r
-            }\r
-            catch (Exception e) {\r
-                Debug.WriteLine(e.Message);\r
-                IsError = true;\r
-            }\r
-            finally {\r
-            }\r
-#if DEBUG\r
-            // Double check to make sure we aren't releasing something\r
-            // important.\r
-            //GC.Collect();\r
-            //GC.WaitForPendingFinalizers();\r
-#endif\r
-        }\r
-\r
-        private static IBaseFilter LoadVideoDecoder(IGraphBuilder graphBuilder) {\r
-            IBaseFilter videoDecoder = null;\r
-            ILAVVideoSettings lavVideoSettings;\r
-            videoDecoder = FilterProvider.GetVideoFilter(out lavVideoSettings);\r
-            if (videoDecoder == null)\r
-                videoDecoder = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Video Decoder");\r
-            else\r
-                graphBuilder.AddFilter(videoDecoder, "LAV Video Decoder");\r
-            return videoDecoder;\r
-        }\r
-\r
-        private static IBaseFilter LoadAudioDecoder(IGraphBuilder graphBuilder) {\r
-            IBaseFilter audioDecoder = null;\r
-            ILAVAudioSettings lavAudioSettings;\r
-            ILAVAudioStatus lavAudioStatus;\r
-            audioDecoder = FilterProvider.GetAudioFilter(out lavAudioSettings, out lavAudioStatus);\r
-            if (audioDecoder == null)\r
-                audioDecoder = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Audio Decoder");\r
-            else\r
-                graphBuilder.AddFilter(audioDecoder, "LAV Audio Decoder");\r
-            return audioDecoder;\r
-        }\r
-\r
-        private static IBaseFilter LoadSplitter(IGraphBuilder graphBuilder) {\r
-            IBaseFilter splitter = null;\r
-            ILAVSplitterSettings lavSplitterSettings;\r
-            splitter = FilterProvider.GetSplitter(out lavSplitterSettings);\r
-            if (splitter == null)\r
-                splitter = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Splitter");\r
-            else\r
-                graphBuilder.AddFilter(splitter, "LAV Splitter");\r
-            return splitter;\r
-        }\r
-\r
         private void SetTimeCodes() {\r
             int hr;\r
             long duration;\r
-            hr = m_mediaSeek.GetDuration(out duration);\r
+            hr = graph.MediaSeeking.GetDuration(out duration);\r
             DsError.ThrowExceptionForHR(hr);\r
             MediaDescription.duration = new Timecode();\r
             MediaDescription.Duration.Set(ReferenceTimeToFrames(duration));\r
@@ -434,18 +255,18 @@ namespace DxPlay {
             int hr;\r
 \r
             // Set the output window\r
-            hr = m_videoWindow.put_Owner(playerWindow.Handle);\r
+            hr = graph.VideoWindow.put_Owner(playerWindow.Handle);\r
             DsError.ThrowExceptionForHR(hr);\r
 \r
-            hr = m_videoWindow.put_MessageDrain(playerWindow.Handle);\r
+            hr = graph.VideoWindow.put_MessageDrain(playerWindow.Handle);\r
             DsError.ThrowExceptionForHR(hr);\r
 \r
             // Set the window style\r
-            hr = m_videoWindow.put_WindowStyle((WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings));\r
+            hr = graph.VideoWindow.put_WindowStyle((WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings));\r
             DsError.ThrowExceptionForHR(hr);\r
 \r
             // Make the window visible\r
-            hr = m_videoWindow.put_Visible(OABool.True);\r
+            hr = graph.VideoWindow.put_Visible(OABool.True);\r
             DsError.ThrowExceptionForHR(hr);\r
 \r
             UpdateVideoWindow();\r
@@ -471,36 +292,32 @@ namespace DxPlay {
                 playerHeight = (int)Math.Ceiling(rc.Right * x); ;\r
             }\r
 \r
-            hr = m_videoWindow.SetWindowPosition((rc.Right - playerWidth) / 2, (rc.Bottom - playerHeight) / 2, playerWidth, playerHeight);\r
+            hr = graph.VideoWindow.SetWindowPosition((rc.Right - playerWidth) / 2, (rc.Bottom - playerHeight) / 2, playerWidth, playerHeight);\r
             DsError.ThrowExceptionForHR(hr);\r
         }\r
 \r
         public void ToggleFullscreen() {\r
-            m_videoWindow.put_FullScreenMode(IsFullscreen() ? OABool.False : OABool.True);\r
+            graph.VideoWindow.put_FullScreenMode(IsFullscreen() ? OABool.False : OABool.True);\r
         }\r
 \r
         public bool IsFullscreen() {\r
             OABool isFullscreen;\r
-            int hr = m_videoWindow.get_FullScreenMode(out isFullscreen);\r
+            int hr = graph.VideoWindow.get_FullScreenMode(out isFullscreen);\r
             DsError.ThrowExceptionForHR(hr);\r
             return isFullscreen == OABool.True ? true : false;\r
         }\r
 \r
         // Set the options on the sample grabber\r
         private void ConfigureSampleGrabber(ISampleGrabber sampGrabber) {\r
-            AMMediaType media;\r
             int hr;\r
-\r
-            // Set the media type to Video/RBG24\r
-            media = new AMMediaType();\r
-            media.majorType = MediaType.Video;\r
-            media.subType = MediaSubType.RGB24;\r
-            media.formatType = FormatType.VideoInfo;\r
-            hr = sampGrabber.SetMediaType(media);\r
-            DsError.ThrowExceptionForHR(hr);\r
-\r
-            DsUtils.FreeAMMediaType(media);\r
-            media = null;\r
+            //AMMediaType media;\r
+            //media = new AMMediaType();\r
+            //media.majorType = MediaType.Video;\r
+            //media.subType = MediaSubType.RGB24;\r
+            //media.formatType = FormatType.VideoInfo;\r
+            //hr = sampGrabber.SetMediaType(media);\r
+            //DsError.ThrowExceptionForHR(hr);\r
+            //DsUtils.FreeAMMediaType(media);\r
 \r
             hr = sampGrabber.SetCallback(this, 1);\r
             DsError.ThrowExceptionForHR(hr);\r
@@ -510,13 +327,11 @@ namespace DxPlay {
             DsError.ThrowExceptionForHR(hr);\r
         }\r
 \r
-        private void SaveSizeInfo(ISampleGrabber sampGrabber) {\r
-            int hr;\r
-\r
-            // Get the media type from the SampleGrabber\r
-            AMMediaType media = new AMMediaType();\r
-            hr = sampGrabber.GetConnectedMediaType(media);\r
-            DsError.ThrowExceptionForHR(hr);\r
+        private void SaveSizeInfo(AMMediaType media) {\r
+            //int hr;\r
+            //AMMediaType media = new AMMediaType();\r
+            //hr = sampGrabber.GetConnectedMediaType(media);\r
+            //DsError.ThrowExceptionForHR(hr);\r
 \r
             if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero)) {\r
                 throw new NotSupportedException("Unknown Grabber Media Format");\r
@@ -528,14 +343,11 @@ namespace DxPlay {
             MediaDescription.frameRate = MEDIATIME_REFERENCE / videoInfoHeader.AvgTimePerFrame;\r
 \r
             m_stride = videoInfoHeader.BmiHeader.Width * (videoInfoHeader.BmiHeader.BitCount / 8);\r
-            DsUtils.FreeAMMediaType(media);\r
-            media = null;\r
         }\r
 \r
         // Shut down capture\r
         private void CloseInterfaces() {\r
             Debug.WriteLine("CloseInterfaces");\r
-            int hr;\r
             GC.SuppressFinalize(this);\r
             if (tcWorker != null)\r
                 tcWorker.CancelAsync();\r
@@ -549,36 +361,8 @@ namespace DxPlay {
                     }\r
                 }\r
 \r
-                if (m_mediaCtrl != null) {\r
-                    // Stop the graph\r
-                    hr = m_mediaCtrl.Stop();\r
-                    FilterGraphTools.DisconnectAllPins((IGraphBuilder)m_mediaCtrl);\r
-                    FilterGraphTools.RemoveAllFilters((IGraphBuilder)m_mediaCtrl);\r
-                    m_mediaCtrl = null;\r
-\r
-                }\r
-\r
-                if (m_videoWindow != null) {\r
-                    hr = m_videoWindow.put_Visible(OABool.False);\r
-                    hr = m_videoWindow.put_MessageDrain(IntPtr.Zero);\r
-                    hr = m_videoWindow.put_Owner(IntPtr.Zero);\r
-                    m_videoWindow = null;\r
-                }\r
-\r
-                m_mediaEvent = null;\r
-                m_mediaSeek = null;\r
-                m_mediaPosition = null;\r
-\r
-#if DEBUG\r
-                if (m_DsRot != null) {\r
-                    m_DsRot.Dispose();\r
-                    m_DsRot = null;\r
-                }\r
-#endif\r
-                if (m_FilterGraph != null) {\r
-                    Marshal.ReleaseComObject(m_FilterGraph);\r
-                    m_FilterGraph = null;\r
-                }\r
+                if (graph != null)\r
+                    graph.Dispose();\r
             }\r
             GC.Collect();\r
             //if (m_eventThread != null)\r
@@ -654,9 +438,9 @@ namespace DxPlay {
                     if (State != GraphState.Exiting) {\r
                         // Read the event\r
                         for (\r
-                            hr = m_mediaEvent.GetEvent(out ec, out p1, out p2, 0);\r
+                            hr = graph.MediaEvent.GetEvent(out ec, out p1, out p2, 0);\r
                             hr >= 0;\r
-                            hr = m_mediaEvent.GetEvent(out ec, out p1, out p2, 0)\r
+                            hr = graph.MediaEvent.GetEvent(out ec, out p1, out p2, 0)\r
                             ) {\r
                             // Write the event name to the debug window\r
                             Debug.WriteLine(ec.ToString());\r
@@ -667,7 +451,7 @@ namespace DxPlay {
                             }\r
 \r
                             // Release any resources the message allocated\r
-                            hr = m_mediaEvent.FreeEventParams(ec, p1, p2);\r
+                            hr = graph.MediaEvent.FreeEventParams(ec, p1, p2);\r
                             DsError.ThrowExceptionForHR(hr);\r
 \r
                             //lock (tcLock) {\r
index 173626563adfa885efcc5e915f40c419c1aa35e8..86d6937b13683e60dc32954df2d059011b7cb832 100644 (file)
@@ -6,6 +6,7 @@ using System.Runtime.InteropServices;
 using System.Security;\r
 using System.Windows.Forms;\r
 \r
+//https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/mapping-stream-formats-to-speaker-configurations\r
 namespace DxPlay {\r
     #region "LAV COM classes"\r
 \r
diff --git a/client/DxPlay/PlayerGraph.cs b/client/DxPlay/PlayerGraph.cs
new file mode 100644 (file)
index 0000000..6527641
--- /dev/null
@@ -0,0 +1,189 @@
+using DirectShowLib;\r
+using DirectShowLib.Utils;\r
+using NLog;\r
+using System;\r
+using System.Runtime.InteropServices;\r
+\r
+namespace DxPlay {\r
+    public class PlayerGraph : FilterGraph, IDisposable {\r
+        #if DEBUG\r
+            private DsROTEntry m_DsRot;\r
+        #endif\r
+        private static readonly Logger logger = LogManager.GetCurrentClassLogger();\r
+        public IVideoWindow VideoWindow { get; private set; }\r
+        public ISampleGrabber SampleGrabber { get; private set; }\r
+        public IMediaSeeking MediaSeeking { get; private set; }\r
+        public IMediaControl MediaControl { get; private set; }\r
+        public IMediaEvent MediaEvent { get; private set; }\r
+\r
+        public PlayerGraph(string fileName) {\r
+            try {\r
+                MediaSeeking = this as IMediaSeeking;\r
+                MediaControl = this as IMediaControl;\r
+                MediaEvent = this as IMediaEvent;\r
+                VideoWindow = this as IVideoWindow;\r
+                IGraphBuilder graphBuilder = this as IGraphBuilder;\r
+#if DEBUG\r
+                m_DsRot = new DsROTEntry(graphBuilder);\r
+#endif\r
+                logger.Debug("Add SourceFilter to graph");\r
+                DsError.ThrowExceptionForHR(graphBuilder.AddSourceFilter(fileName, fileName, out IBaseFilter sourceFilter));\r
+\r
+                IBaseFilter splitter = AddSplitter(graphBuilder, sourceFilter);\r
+                IBaseFilter videoDecoder = AddVideoDecoder(graphBuilder, splitter);\r
+                IBaseFilter sampleGrabber = AddSampleGrabber(graphBuilder, videoDecoder);\r
+                SampleGrabber = (ISampleGrabber)sampleGrabber;\r
+                IBaseFilter videoRenderer = AddRenderer(graphBuilder, sampleGrabber);\r
+                if (DsFindPin.ByName(splitter, "Audio") != null) {\r
+                    IBaseFilter audioDecoder = AddAudioDecoder(graphBuilder, splitter);\r
+                    FilterGraphTools.RenderPin(graphBuilder, audioDecoder, "Output");\r
+                } else {\r
+                    logger.Warn("Audio pin not available");\r
+                }\r
+\r
+                SearchAudioTracks(splitter);\r
+                EnableDeinterlace(videoDecoder);\r
+            }\r
+            catch (Exception e) {\r
+                logger.Error(e.Message);\r
+            }\r
+        }\r
+\r
+        private void EnableDeinterlace(IBaseFilter videoDecoder) {\r
+            logger.Debug("Enable YADIF deinterlace");\r
+            ILAVVideoSettings settings = (ILAVVideoSettings)videoDecoder;\r
+            settings.SetSWDeintMode(LAVSWDeintModes.SWDeintMode_YADIF);\r
+            settings.SetSWDeintOutput(LAVDeintOutput.DeintOutput_FramePer2Field);\r
+        }\r
+\r
+        private IBaseFilter AddAudioDecoder(IGraphBuilder graphBuilder, IBaseFilter splitter) {\r
+            logger.Debug("Add LAVAudio to graph");\r
+            IBaseFilter audioDecoder = null;\r
+            audioDecoder = LoadAudioDecoder(graphBuilder);\r
+            if (audioDecoder == null)\r
+                throw new Exception("No audio decoder!");\r
+\r
+            logger.Debug("Connect LAVSplitter -> LAVAudio");\r
+            FilterGraphTools.ConnectFilters(graphBuilder, splitter, "Audio", audioDecoder, "Input", true);\r
+            return audioDecoder;\r
+        }\r
+\r
+        private IBaseFilter AddRenderer(IGraphBuilder graphBuilder, IBaseFilter sampleGrabber) {\r
+            logger.Debug("Add VideoMixingRenderer9 to graph");\r
+            IBaseFilter videoRenderer = (IBaseFilter)new VideoMixingRenderer9();\r
+            DsError.ThrowExceptionForHR(graphBuilder.AddFilter(videoRenderer, "Video Mixing Renderer 9"));\r
+\r
+            logger.Debug("Connect SampleGrabber -> VideoMixingRenderer9");\r
+            FilterGraphTools.ConnectFilters(graphBuilder, sampleGrabber, "Output", videoRenderer, "VMR Input0", true);\r
+            return videoRenderer;\r
+        }\r
+\r
+        private IBaseFilter AddSampleGrabber(IGraphBuilder graphBuilder, IBaseFilter videoDecoder) {\r
+            logger.Debug("Add SampleGrabber to graph");\r
+            IBaseFilter grabber = (IBaseFilter)new SampleGrabber();\r
+            DsError.ThrowExceptionForHR(graphBuilder.AddFilter(grabber, "Sample Grabber"));\r
+            logger.Debug("Connect LAVVideo -> SampleGrabber");\r
+            FilterGraphTools.ConnectFilters(graphBuilder, videoDecoder, "Output", grabber, "Input", true);\r
+            return grabber;\r
+        }\r
+\r
+        private IBaseFilter AddVideoDecoder(IGraphBuilder graphBuilder, IBaseFilter splitter) {\r
+            logger.Debug("Add LAVVideo to graph");\r
+            IBaseFilter videoDecoder = LoadVideoDecoder(graphBuilder);\r
+\r
+            if (videoDecoder == null)\r
+                throw new Exception("No video decoder!");\r
+\r
+            logger.Debug("Connect LAVSplitter -> LAVVideo");\r
+            FilterGraphTools.ConnectFilters(graphBuilder, splitter, "Video", videoDecoder, "Input", true);\r
+            return videoDecoder;\r
+        }\r
+\r
+        private IBaseFilter AddSplitter(IGraphBuilder graphBuilder, IBaseFilter sourceFilter) {\r
+            logger.Debug("Add LAVSplitter to graph");\r
+            IBaseFilter splitter = LoadSplitter(graphBuilder);\r
+            if (splitter == null)\r
+                throw new Exception("No splitter!");\r
+            logger.Debug("Connect SourceFilter -> LAVSplitter");\r
+            FilterGraphTools.ConnectFilters(graphBuilder, sourceFilter, "Output", splitter, "Input", true);\r
+            return splitter;\r
+        }\r
+\r
+        private void SearchAudioTracks(IBaseFilter splitter) {\r
+            IAMStreamSelect amStreamSelect = (IAMStreamSelect)splitter;\r
+            if (amStreamSelect != null) {\r
+                int count = 0;\r
+                amStreamSelect.Count(out count);\r
+                int audioCount = 0;\r
+                for (int i = 0; i < count; i++) {\r
+                    amStreamSelect.Info(i, out AMMediaType ppmt, out AMStreamSelectInfoFlags pdwFlags, out int plcid, out int pdwGroup, out string ppszName, out object ppObject, out object ppUnk);\r
+                    if (ppmt.majorType == MediaType.Audio) {\r
+                        logger.Debug("Found audio channel");\r
+                        audioCount++;\r
+                    }\r
+                    DsUtils.FreeAMMediaType(ppmt);\r
+                    if (ppObject != null)\r
+                        DsUtils.ReleaseComObject(ppObject);\r
+                    if (ppUnk != null)\r
+                        DsUtils.ReleaseComObject(ppUnk);\r
+                }\r
+                logger.Debug("Audio count: " + audioCount);\r
+            }\r
+        }\r
+\r
+        private IBaseFilter LoadVideoDecoder(IGraphBuilder graphBuilder) {\r
+            IBaseFilter videoDecoder = null;\r
+            ILAVVideoSettings lavVideoSettings;\r
+            videoDecoder = FilterProvider.GetVideoFilter(out lavVideoSettings);\r
+            if (videoDecoder == null)\r
+                videoDecoder = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Video Decoder");\r
+            else\r
+                graphBuilder.AddFilter(videoDecoder, "LAV Video Decoder");\r
+            return videoDecoder;\r
+        }\r
+\r
+        private IBaseFilter LoadAudioDecoder(IGraphBuilder graphBuilder) {\r
+            IBaseFilter audioDecoder = null;\r
+            ILAVAudioSettings lavAudioSettings;\r
+            ILAVAudioStatus lavAudioStatus;\r
+            audioDecoder = FilterProvider.GetAudioFilter(out lavAudioSettings, out lavAudioStatus);\r
+            if (audioDecoder == null)\r
+                audioDecoder = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Audio Decoder");\r
+            else\r
+                graphBuilder.AddFilter(audioDecoder, "LAV Audio Decoder");\r
+            return audioDecoder;\r
+        }\r
+\r
+        private IBaseFilter LoadSplitter(IGraphBuilder graphBuilder) {\r
+            IBaseFilter splitter = null;\r
+            ILAVSplitterSettings lavSplitterSettings;\r
+            splitter = FilterProvider.GetSplitter(out lavSplitterSettings);\r
+            if (splitter == null)\r
+                splitter = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "LAV Splitter");\r
+            else\r
+                graphBuilder.AddFilter(splitter, "LAV Splitter");\r
+            return splitter;\r
+        }\r
+\r
+        // Shut down capture\r
+        public void Dispose() {\r
+            logger.Debug("CloseInterfaces");\r
+            lock (this) {\r
+#if DEBUG\r
+                if (m_DsRot != null)\r
+                    m_DsRot.Dispose();\r
+#endif\r
+                IMediaControl mediaCtrl = (IMediaControl) this;\r
+                if (mediaCtrl != null) {\r
+                    mediaCtrl.Stop();\r
+                    IGraphBuilder graphBuilder = (IGraphBuilder)mediaCtrl;\r
+                    FilterGraphTools.DisconnectAllPins(graphBuilder);\r
+                    FilterGraphTools.RemoveAllFilters(graphBuilder);\r
+                }\r
+\r
+                Marshal.ReleaseComObject(this);\r
+            }\r
+        }\r
+\r
+    }\r
+}\r
index 011df72e24affe1b54067845a9943203dee8e3aa..bbf85d24fb0c9b2bd3833c83556dafda817a5832 100644 (file)
@@ -3,7 +3,7 @@
       "active": false,\r
       "executeimmediate": false,\r
          "name" : "SYS: recreate-lowres",\r
-      "template": "recreate-lowres.xml",\r
+      "template": "sys-recreate-lowres.xml",\r
       "parameters": [ \r
        {"name": "filePath", "value": "c:/_downloads/Silicon.Valley.S04E08.HDTV.x264.HUN-SFY/Silicon.Valley.S04E08.HDTV.x264.HUN-SFY.mkv", "type": "java.lang.String" }\r
       ]\r
index d4677b2fe4c87b2e741fde045524c4d940223a6e..0193802ca5104d1ac901a569d2d998dfcbd2dbef 100644 (file)
@@ -3,6 +3,7 @@
        <executor className="user.jobengine.server.steps.ArchiveListBuilderStep" maxConcurrent="1"/>\r
        <executor className="user.jobengine.server.steps.ArchiveMaterialSubmitStep" maxConcurrent="1"/>\r
        <executor className="user.jobengine.server.steps.BatchRetrieveForkStep" maxConcurrent="10"/>\r
+       <executor className="user.jobengine.server.steps.CheckLOWRESIntegrity" maxConcurrent="1"/>\r
        <executor className="user.jobengine.server.steps.CheckMORPHEUSMissingMaterialsStep" maxConcurrent="1"/>\r
        <executor className="user.jobengine.server.steps.CheckTRAFFICMissingMaterialsStep" maxConcurrent="1"/>\r
        <executor className="user.jobengine.server.steps.CleanupMountedLocationStep" maxConcurrent="10"/>\r
@@ -26,5 +27,4 @@
        <executor className="user.jobengine.server.steps.TSMRetrieveMissingMaterialStep" maxConcurrent="1"/>\r
        <executor className="user.jobengine.server.steps.UploadRecordingToNexioStep" maxConcurrent="1"/>\r
        <executor className="user.jobengine.server.steps.MediaToolStep" maxConcurrent="1"/>\r
-       \r
 </executors>
\ No newline at end of file
index f4e0d2ac3dc8b7e08486bd7d24a8339d924bcb50..1574ddb3e1b3de6afd89262056394790a96c25f3 100644 (file)
@@ -1,4 +1,11 @@
 {"joblist":[\r
+       {\r
+         "name" : "sys: Check LOWRES integrity",\r
+      "template": "check-lowres-integrity.xml",\r
+      "parameters": [ \r
+       {"name": "webPath", "value": "/mediacube/data/lowres/www/video", "type": "java.lang.String"}\r
+      ]\r
+       },\r
        {\r
       "active": false,\r
       "executeimmediate": false,\r
diff --git a/server/user.jobengine.executors/jobtemplates/sys-check-lowres-integrity.xml b/server/user.jobengine.executors/jobtemplates/sys-check-lowres-integrity.xml
new file mode 100644 (file)
index 0000000..4c5e181
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<jobtemplate name="Felhasználói archiválás">\r
+       <declarations>\r
+               <parameters>\r
+                       <parameter name="webPath" type="java.lang.String" />\r
+               </parameters>\r
+       </declarations>\r
+       <commands>\r
+               <calljobstep type="user.jobengine.server.steps.CheckLOWRESIntegrity" weight="1">\r
+                       <inputs>\r
+                               <input>\r
+                                       <parameter name="webPath" />\r
+                               </input>\r
+                       </inputs>\r
+               </calljobstep>\r
+       </commands>\r
+</jobtemplate>
\ No newline at end of file
diff --git a/server/user.jobengine.executors/jobtemplates/sys-recreate-length.xml b/server/user.jobengine.executors/jobtemplates/sys-recreate-length.xml
new file mode 100644 (file)
index 0000000..44c0e09
--- /dev/null
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<jobtemplate name="Visszarögzített anyagok archiválása mappából">\r
+       <declarations>\r
+               <parameters>\r
+                       <parameter name="localHiresPath" type="java.lang.String" />\r
+                       <parameter name="globalHiresPath" type="java.lang.String" />\r
+               </parameters>\r
+               <variables>\r
+                       <variable name="mediaCubeMedia" type="user.jobengine.db.Media" />\r
+                       <variable name="targetNamePattern" type="java.lang.String" />\r
+                       <variable name="archiveItem" type="user.jobengine.server.steps.ArchiveItem" />\r
+                       <variable name="killDateDays" type="java.lang.Integer"/>\r
+                       <variable name="successRecipient" type="java.lang.String" />\r
+                       <variable name="deleteSource" type="java.lang.Boolean"/>\r
+               </variables>\r
+       </declarations>\r
+       <commands>\r
+               <calljobstep type="user.jobengine.server.steps.DetectMissingLengthStep" weight="1">\r
+                       <inputs>\r
+                               <input>\r
+                                       <parameter name="localHiresPath" />\r
+                               </input>\r
+                       </inputs>\r
+                       <outputs>\r
+                               <output>\r
+                                       <variable name="mediaCubeMedia" />\r
+                               </output>\r
+                               <output>\r
+                                       <variable name="archiveItem" />\r
+                               </output>\r
+                               <output>\r
+                                       <variable name="targetNamePattern" />\r
+                               </output>\r
+                               <output>\r
+                                       <variable name="successRecipient" />\r
+                               </output>\r
+                               <output>\r
+                                       <variable name="killDateDays" />\r
+                               </output>\r
+                               <output>\r
+                                       <variable name="deleteSource" />\r
+                               </output>\r
+                       </outputs>\r
+               </calljobstep>\r
+               <calljobstep type="user.jobengine.server.steps.TSMRestoreStep" weight="1">\r
+                       <inputs>\r
+                               <input>\r
+                                       <variable name="mediaCubeMedia" />\r
+                               </input>\r
+                               <input>\r
+                                       <parameter name="localHiresPath" />\r
+                               </input>\r
+                               <input>\r
+                                       <variable name="targetNamePattern" />\r
+                               </input>\r
+                               <input>\r
+                                       <variable name="successRecipient" />\r
+                               </input>\r
+                               <input>\r
+                                       <variable name="killDateDays" />\r
+                               </input>\r
+                       </inputs>\r
+               </calljobstep>\r
+               <calljobstep type="user.jobengine.server.steps.MediaToolStep" weight="1">\r
+                       <inputs>\r
+                               <input>\r
+                                       <variable name="archiveItem" />\r
+                               </input>\r
+                               <input>\r
+                                       <variable name="mediaCubeMedia" />\r
+                               </input>\r
+                       </inputs>\r
+               </calljobstep>\r
+       </commands>\r
+</jobtemplate>
\ No newline at end of file
diff --git a/server/user.jobengine.executors/src/user/jobengine/server/steps/CheckLOWRESIntegrity.java b/server/user.jobengine.executors/src/user/jobengine/server/steps/CheckLOWRESIntegrity.java
new file mode 100644 (file)
index 0000000..5cc8169
--- /dev/null
@@ -0,0 +1,66 @@
+package user.jobengine.server.steps;\r
+\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.logging.log4j.LogManager;\r
+import org.apache.logging.log4j.Logger;\r
+import org.apache.logging.log4j.Marker;\r
+\r
+import user.jobengine.db.IItemManager;\r
+import user.jobengine.db.IResultSetConsumer;\r
+import user.jobengine.db.Media;\r
+import user.jobengine.db.MediaFile;\r
+import user.jobengine.server.IJobEngine;\r
+import user.jobengine.server.IJobRuntime;\r
+\r
+public class CheckLOWRESIntegrity extends JobStep {\r
+       private static final Logger logger = LogManager.getLogger();\r
+       private IItemManager manager;\r
+       private Marker marker;\r
+       private String webPath;\r
+\r
+       private void checkIntegrity(MediaFile mediaFile) {\r
+               Path path = Paths.get(webPath, mediaFile.getRelativePath());\r
+               if (!path.toFile().exists()) {\r
+                       logger.warn(marker, "{} {}", mediaFile.getId(), path);\r
+               }\r
+       }\r
+\r
+       @StepEntry\r
+       public Object[] execute(String webPath, IJobEngine jobEngine, IJobRuntime jobRuntime) throws Exception {\r
+               this.webPath = webPath;\r
+               marker = jobRuntime.getMarker();\r
+               manager = jobEngine.getItemManager();\r
+               List<Long> mediaIdentities = getTranscodedMediaIdentities();\r
+               int allCount = mediaIdentities.size();\r
+               int currentCount = 0;\r
+               for (long id : mediaIdentities) {\r
+                       Media media = manager.getMedia(id);\r
+                       List<MediaFile> mediaFiles = media.getMediaFiles();\r
+                       for (MediaFile mediaFile : mediaFiles) {\r
+                               if (mediaFile.getStoreId() == 21)\r
+                                       checkIntegrity(mediaFile);\r
+                       }\r
+                       currentCount++;\r
+                       jobRuntime.incrementProgress(currentCount * 100 / allCount);\r
+               }\r
+               return null;\r
+       }\r
+\r
+       public List<Long> getTranscodedMediaIdentities() {\r
+               final List<Long> result = new ArrayList<>();\r
+               String query = "select mediaid from vw_mediafiles where mediafilecount = 2";\r
+\r
+               IResultSetConsumer consumer = rs -> {\r
+                       result.add(rs.getLong("mediaId"));\r
+                       return true;\r
+               };\r
+\r
+               manager.executeQuery(query, consumer, null);\r
+               return result;\r
+       }\r
+\r
+}\r
index 5627362f3573ca9684f09075104fe6236f491070..d164358583def22ebc18fb58e27e919c9f903fc7 100644 (file)
@@ -13,6 +13,7 @@ import org.apache.commons.net.ftp.FTPClient;
 import org.apache.commons.net.ftp.FTPReply;\r
 import org.apache.logging.log4j.LogManager;\r
 import org.apache.logging.log4j.Logger;\r
+import org.apache.logging.log4j.Marker;\r
 \r
 import com.ibm.nosql.json.api.BasicDBObject;\r
 import com.ibm.nosql.json.api.DB;\r
@@ -56,10 +57,11 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
        private StoreUri targetUri;\r
        private int nexioKillDateDays;\r
        private String nexioAgency;\r
+       private Marker systemMarker;\r
 \r
        private int check(int value, String name) {\r
                if (value == 0) {\r
-                       logger.error(getMarker(), "A folyamat '{}' bemeneti paramétere 0.", name);\r
+                       logger.error(systemMarker, "A folyamat '{}' bemeneti paramétere 0.", name);\r
                        throw new NullPointerException(String.format("System is not configured properly, missing '%s' input parameter.", name));\r
                }\r
                return value;\r
@@ -67,7 +69,7 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
 \r
        private String check(String value, String name) {\r
                if (value == null) {\r
-                       logger.error(getMarker(), "A folyamat '{}' bemeneti paramétere üres.", name);\r
+                       logger.error(systemMarker, "A folyamat '{}' bemeneti paramétere üres.", name);\r
                        throw new NullPointerException(String.format("System is not configured properly, missing '%s' input parameter.", name));\r
                }\r
                return value;\r
@@ -79,7 +81,7 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
                                try {\r
                                        copyFile(fileArchive, rundownArchive, storyArchive);\r
                                } catch (Exception e) {\r
-                                       logger.error(getMarker(), "A '{}' clip archiválása sikertelen. A rendszer üzenete: {}", fileArchive.getFileName(), e.getMessage());\r
+                                       logger.error(systemMarker, "A '{}' clip archiválása sikertelen. A rendszer üzenete: {}", fileArchive.getFileName(), e.getMessage());\r
                                }\r
                        }\r
                }\r
@@ -144,13 +146,14 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
        @StepEntry\r
        public Object[] execute(int nexioPort, String nexioUserName, String nexioPassword, String archiveFtp, String archiveUserName, String archivePassword,\r
                        int daysBeforeNow, int nexioKillDateDays, String nexioAgency, IJobEngine jobEngine, IJobRuntime jobRuntime) throws Exception {\r
+               systemMarker = jobRuntime.getMarker();\r
                setAndCheck(nexioPort, nexioUserName, nexioPassword, archiveFtp, archiveUserName, archivePassword, nexioKillDateDays, nexioAgency, jobEngine);\r
                octopusAPI = new OctopusAPI();\r
                Calendar scheduledDate = Calendar.getInstance();\r
                scheduledDate.add(Calendar.DAY_OF_YEAR, -1 * daysBeforeNow);\r
                List<DBObject> rundowns = octopusAPI.getRundowns(scheduledDate.getTime());\r
                if (rundowns == null) {\r
-                       logger.warn(getMarker(), "Nem található adástükör a {} napra.", CalendarUtils.toDateString(scheduledDate));\r
+                       logger.warn(systemMarker, "Nem található adástükör a {} napra.", CalendarUtils.toDateString(scheduledDate));\r
                        return null;\r
                }\r
 \r
@@ -264,7 +267,7 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
                                db.getCollection(ARCHIVEDRUNDOWNS).save(currentRundownID);\r
                        } catch (Exception e) {\r
                                logger.catching(e);\r
-                               logger.error(getMarker(),\r
+                               logger.error(systemMarker,\r
                                                String.format("A %s %s tükör archiválása nem lehetséges, mert a annak ellenőrzése hibát jelzett. A rendszer üzenete: %s", rundownID,\r
                                                                rundownName, e.getMessage()));\r
                        }\r
@@ -315,22 +318,22 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
                        int nexioKillDateDays, String nexioAgency, IJobEngine jobEngine) throws Exception {\r
                db = NoSQLUtils.getNoSQLDB();\r
                if (db == null) {\r
-                       logger.error(getMarker(), "Az NoSQL adatkezelő réteg nem elérhető.");\r
+                       logger.error(systemMarker, "Az NoSQL adatkezelő réteg nem elérhető.");\r
                        throw new NullPointerException("Internal error, missing NoSQL DB reference.");\r
                }\r
 \r
                if (jobEngine == null) {\r
-                       logger.error(getMarker(), "Az folyamatkezelő réteg nem elérhető.");\r
+                       logger.error(systemMarker, "Az folyamatkezelő réteg nem elérhető.");\r
                        throw new NullPointerException("Internal error, missing JobEngine reference.");\r
                }\r
                manager = jobEngine.getItemManager();\r
                if (manager == null) {\r
-                       logger.error(getMarker(), "Az adatbáziskezelő réteg nem elérhető.");\r
+                       logger.error(systemMarker, "Az adatbáziskezelő réteg nem elérhető.");\r
                        throw new NullPointerException("Internal error, missing ItemManager reference.");\r
                }\r
                String nexioHost = System.getProperty("nexio.host");\r
                if (StringUtils.isBlank(nexioHost)) {\r
-                       logger.error(getMarker(), "A 'nexio.host' rendszer paraméter nem található.");\r
+                       logger.error(systemMarker, "A 'nexio.host' rendszer paraméter nem található.");\r
                        throw new NullPointerException("System is not configured properly, 'jobengine.selenio.address' startup parameter missing.");\r
                }\r
                check(nexioPort, "nexioPort");\r
@@ -347,7 +350,7 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
                sourceUri.setUserName(nexioUserName);\r
                sourceUri.setPassword(nexioPassword);\r
                if (sourceUri == null) {\r
-                       logger.error(getMarker(), "A forrás nem elérhető.");\r
+                       logger.error(systemMarker, "A forrás nem elérhető.");\r
                        throw new NullPointerException("Internal error, missing 'sourceUri'.");\r
                }\r
 \r
@@ -359,7 +362,7 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
                targetUri.setUserName(archiveUserName);\r
                targetUri.setPassword(archivePassword);\r
                if (targetUri == null) {\r
-                       logger.error(getMarker(), "A cél nem elérhető.");\r
+                       logger.error(systemMarker, "A cél nem elérhető.");\r
                        throw new NullPointerException("Internal error, missing 'targetUri'.");\r
                }\r
 \r
@@ -369,6 +372,7 @@ public class CopyForArchiveNEXIOMaterialsStep extends JobStep {
                logger.info("Transfer chunk {}", fileName);\r
                OutputStream outStream = null;\r
                try {\r
+                       targetFtp = ((FtpDirectoryLister) targetUri.getLister()).connect();\r
                        outStream = targetFtp.storeFileStream(fileName + MXFEXT);\r
                        if (outStream == null) {\r
                                throw new NullPointerException("Can not open: " + fileName + MXFEXT + " Reply:" + targetFtp.getReplyString());\r
index 76abc690f901da05afe59c864c088d94cc4fe153..cc7ce391b8a050857618b937b6f1f3cdc96ec8bf 100644 (file)
@@ -39,6 +39,8 @@ public class CreateMissingLowresStep extends JobStep {
 \r
                        for (Media media : medias) {\r
                                String name = media.getMediaFilesName();\r
+                               if (name == null)\r
+                                       continue;\r
                                DBObject existing = collection.findOne(new BasicDBObject("name", name));\r
                                if (existing != null)\r
                                        continue;\r
index 20592bec295991c8f67f11ff48f21ef19e453a39..d89aca15cabb0681a6f2cdd231e30ec218ea9bef 100644 (file)
@@ -29,6 +29,7 @@ import user.jobengine.server.IJobRuntime;
 import user.jobengine.server.JobEngineException;\r
 \r
 public class TSMBackupStep extends JobStep {\r
+       private static final String MXFEXT = ".MXF";\r
        private static final Logger logger = LogManager.getLogger();\r
        private IItemManager manager;\r
        private File sourceMediaFile;\r
@@ -50,7 +51,12 @@ public class TSMBackupStep extends JobStep {
 \r
                        jobRuntime.setDescription(String.format("%s: %s", jobRuntime.getDescription(), details));\r
 \r
-                       if (archiveItem.getExistingMediaId() == 0) {\r
+                       //A dupla ellenorzes a napon beluli ismetlesek miatt kell\r
+                       long existingMediaId = archiveItem.getExistingMediaId();\r
+                       if (existingMediaId == 0)\r
+                               existingMediaId = manager.getExistingRundownMedia(sourceFileName.replace(MXFEXT, ""));\r
+\r
+                       if (existingMediaId == 0) {\r
                                StoreUri sourceUri = manager.createStoreUri(RemoteStoreProtocol.LOCAL, sourceMediaFile.getParent().toString());\r
 \r
                                final IJobRuntime runtime = jobRuntime;\r
@@ -70,7 +76,7 @@ public class TSMBackupStep extends JobStep {
                        } else {\r
                                logger.info(marker, "Az '{}' TSM mentése nem szükséges, mert már megtalálható az archívumban.", sourceFileName);\r
                        }\r
-                       saveMetadata(mediaCubeMedia, sourceFileName, archiveItem);\r
+                       saveMetadata(mediaCubeMedia, sourceFileName, existingMediaId);\r
                        logger.info(marker, "Az '{}' archiválása sikeres.", sourceFileName);\r
 \r
                        if (killDateDays > 0)\r
@@ -88,13 +94,14 @@ public class TSMBackupStep extends JobStep {
                return null;\r
        }\r
 \r
-       private void saveMetadata(Media mediaCubeMedia, String sourceFileName, ArchiveItem archiveItem) {\r
-               if (archiveItem.getExistingMediaId() == 0) {\r
+       private void saveMetadata(Media mediaCubeMedia, String sourceFileName, long existingMediaId) {\r
+\r
+               if (existingMediaId == 0) {\r
                        MediaFile mediaFile = manager.createMediaFile(sourceFileName, fileType, tsmStore, mediaCubeMedia);\r
                        mediaFile.setHouseId(sourceFileName);\r
                        mediaFile.add();\r
                } else {\r
-                       Media existingMedia = manager.getMedia(archiveItem.getExistingMediaId());\r
+                       Media existingMedia = manager.getMedia(existingMediaId);\r
                        List<MediaFile> mediaFiles = existingMedia.getMediaFiles();\r
                        if (mediaFiles != null) {\r
                                for (MediaFile mf : mediaFiles) {\r
index 4a95df9d879ee133fdc7075811b14d32c2e6b50d..9b98c4bb04c069fe020ee80103a401d0a7da0891 100644 (file)
@@ -53,16 +53,21 @@ public class TranscodeFFAStranStep extends JobStep {
                String details = String.format("%s (%d bytes)", sourceFileName, sourceMediaFile.length());\r
                Path targetPath = null;\r
                try {\r
-                       String sourceFile = Paths.get(globalHiresSourcePath, sourceFileName).toString();\r
-                       IFFAStransAPI api = new FFAStransAPI(transcoderAddress, p -> {\r
-                               if (p <= 100)\r
-                                       jobRuntime.incrementProgress(p);\r
-                       });\r
-                       api.submit(transcoderTemplateName, sourceFile);\r
-                       jobRuntime.setDescription(String.format("%s: %s", jobRuntime.getDescription(), details));\r
-                       api.monitor(1000);\r
                        targetPath = Paths.get(localLowresTargetPath, sourceFileName.replace(MXFEXT, MP4EXT));\r
+                       if (!targetPath.toFile().exists()) {\r
+                               jobRuntime.setDescription(String.format("%s: %s", jobRuntime.getDescription(), details));\r
+                               String sourceFile = Paths.get(globalHiresSourcePath, sourceFileName).toString();\r
+                               IFFAStransAPI api = new FFAStransAPI(transcoderAddress, p -> {\r
+                                       if (p <= 100)\r
+                                               jobRuntime.incrementProgress(p);\r
+                               });\r
+\r
+                               api.submit(transcoderTemplateName, sourceFile);\r
+                               api.monitor(1000);\r
+                       }\r
+\r
                        postprocess(targetPath, webPath);\r
+\r
                } catch (Exception e) {\r
                        logger.catching(e);\r
                        Message m = new ParameterizedMessage("Az '{}' állomány átkódolása sikertelen. A rendszer hibaüzenete: {}", details, e.getMessage());\r
@@ -89,17 +94,26 @@ public class TranscodeFFAStranStep extends JobStep {
                Path lowresPath = null;\r
                try {\r
                        String transcodedFileName = transcodedFilePath.getFileName().toString();\r
+                       String targetPath = null;\r
                        if (transcodedFileName.indexOf(".") > 2) {\r
                                Path subdir = Paths.get(transcodedFileName.substring(0, 1), transcodedFileName.substring(1, 2), transcodedFileName.substring(2, 3));\r
-                               manager.createMediaFile(Paths.get(subdir.toString(), transcodedFileName).toString(), fileType, store, mediaCubeMedia).add();\r
                                EscortFiles.ensureUNCFolder(webPath, subdir.toString());\r
-                               lowresPath = Paths.get(webPath, subdir.toString(), transcodedFileName);\r
-                               Files.move(transcodedFilePath, lowresPath);\r
+                               targetPath = Paths.get(subdir.toString(), transcodedFileName).toString();\r
                        } else {\r
-                               manager.createMediaFile(transcodedFileName, fileType, store, mediaCubeMedia).add();\r
-                               lowresPath = Paths.get(webPath, transcodedFileName);\r
-                               Files.move(transcodedFilePath, lowresPath);\r
+                               targetPath = transcodedFileName;\r
+                       }\r
+                       lowresPath = Paths.get(webPath, targetPath);\r
+                       int version = 1;\r
+                       while (lowresPath.toFile().exists()) {\r
+                               String fileName = transcodedFileName + version + MP4EXT;\r
+                               lowresPath = Paths.get(lowresPath.toString().replace(transcodedFileName, fileName));\r
+                               targetPath = targetPath.replace(transcodedFileName, fileName);\r
+                               transcodedFileName = fileName;\r
+                               version++;\r
                        }\r
+\r
+                       Files.move(transcodedFilePath, lowresPath);\r
+                       manager.createMediaFile(targetPath, fileType, store, mediaCubeMedia).add();\r
                } catch (IOException e) {\r
                        logger.catching(e);\r
                        logger.error(marker, "A '{}' állomány mozgatása a '{}' helyre nem sikerült.", transcodedFilePath, lowresPath);\r
index 51f6bacdb41d264260e34e16a49bb3239d967ff6..7f1f21b2a6ae44f531ff4b99bea0cfcf52f3fe05 100644 (file)
@@ -43,6 +43,7 @@ import user.jobengine.server.IJobRuntime;
 \r
 public class TranscodeSELENIOStep extends JobStep {\r
 \r
+       private static final String MXFEXT = ".MXF";\r
        private static final String LOWRES_FILETYPE = "Low-res";\r
        private static final Logger logger = LogManager.getLogger();\r
        private final List<State> showStoppers = Arrays.asList(State.CANCELLED, State.COMPLETE, State.FAILED);\r
@@ -94,15 +95,20 @@ public class TranscodeSELENIOStep extends JobStep {
                marker = jobRuntime.getMarker();\r
                String sourceFileName = null;\r
 \r
-               //Nincs mit transzkódolni\r
-               if (archiveItem.getExistingMediaId() != 0)\r
-                       return null;\r
-\r
                try {\r
                        setAndCheck(globalSourcePath, transcoderTargetPath, webPath, jobEngine);\r
 \r
                        File sourceMediaFile = new File(archiveItem.getMediaFile());\r
                        sourceFileName = sourceMediaFile.getName();\r
+\r
+                       //Nincs mit transzkódolni, a TSMBackupStep csinal masolatot a mediafileokrol\r
+                       //A dupla ellenorzes a napon beluli ismetlesek miatt kell\r
+                       long existingMediaId = archiveItem.getExistingMediaId();\r
+                       if (existingMediaId == 0)\r
+                               existingMediaId = manager.getExistingRundownMedia(sourceFileName.replace(MXFEXT, ""));\r
+                       if (existingMediaId != 0)\r
+                               return null;\r
+\r
                        String details = String.format("%s (%d bytes)", sourceFileName, sourceMediaFile.length());\r
 \r
                        Path inputPath = Paths.get(globalSourcePath, sourceFileName);\r
index 55c4df673ed91972718fd18dfc82edcb6093a029..cabb330ec2c2846ecd3e7dfd2dac0052417e33e7 100644 (file)
@@ -52,12 +52,28 @@ public class FFAStransAPI implements IFFAStransAPI {
        private ResteasyWebTarget webTarget;\r
        private IProgressChangedListener listener;\r
        private String jobId;\r
+       private BasicDBObject lastJobToSubmit;\r
 \r
        public FFAStransAPI(String apiAddress, IProgressChangedListener listener) {\r
                this.listener = listener;\r
                webTarget = new ResteasyClientBuilder().build().target(apiAddress);\r
        }\r
 \r
+       private void doSubmit() throws Exception {\r
+               ResteasyWebTarget target = webTarget.path("jobs");\r
+               Response apiResponse = target.request().post(Entity.entity(lastJobToSubmit.toString(), MediaType.APPLICATION_JSON));\r
+               if (apiResponse.getStatus() != 202)\r
+                       throw new Exception("Can not submit, response status is: " + apiResponse.getStatus());\r
+               String json = apiResponse.readEntity(String.class);\r
+               logger.info("Transoder response: {}", json);\r
+               if (StringUtils.isBlank(json))\r
+                       throw new Exception("Can not submit, response JSON is empty");\r
+               BasicDBObject resultObject = (BasicDBObject) JSONUtil.jsonToDbObject(json);\r
+               if (resultObject == null)\r
+                       throw new Exception("Can not submit, response object is null");\r
+               jobId = resultObject.getString("job_id");\r
+       }\r
+\r
        @Override\r
        public BasicDBObject getHistory(String jobStart) {\r
                ResteasyWebTarget target = webTarget.path("history");\r
@@ -168,6 +184,15 @@ public class FFAStransAPI implements IFFAStransAPI {
                                //System.out.println("Progress: " + 100);\r
                                listener.onProgressChanged(100);\r
                                BasicDBObject history = getHistory(jobStart);\r
+\r
+                               if (history == null && lastJobToSubmit != null) {\r
+                                       //plusz 1 proba\r
+                                       doSubmit();\r
+                                       lastJobToSubmit = null;\r
+                                       monitor(pollIntervall);\r
+                                       return;\r
+                               }\r
+\r
                                //System.out.println("History: " + history.toPrettyString(null));\r
                                if (history == null || NoSQLUtils.asLong(history, "state") != 1) {\r
                                        String error = NoSQLUtils.asString(history, "outcome");\r
@@ -194,18 +219,7 @@ public class FFAStransAPI implements IFFAStransAPI {
                if (wfID < 0)\r
                        throw new Exception("Workflow not exists: " + workflowName);\r
 \r
-               BasicDBObject job = new BasicDBObject("wf_id", wfID).append("inputfile", inputFile);\r
-               ResteasyWebTarget target = webTarget.path("jobs");\r
-               Response apiResponse = target.request().post(Entity.entity(job.toString(), MediaType.APPLICATION_JSON));\r
-               if (apiResponse.getStatus() != 202)\r
-                       throw new Exception("Can not submit, response status is: " + apiResponse.getStatus());\r
-               String json = apiResponse.readEntity(String.class);\r
-               logger.info("Transoder response: {}", json);\r
-               if (StringUtils.isBlank(json))\r
-                       throw new Exception("Can not submit, response JSON is empty");\r
-               BasicDBObject resultObject = (BasicDBObject) JSONUtil.jsonToDbObject(json);\r
-               if (resultObject == null)\r
-                       throw new Exception("Can not submit, response object is null");\r
-               jobId = resultObject.getString("job_id");\r
+               lastJobToSubmit = new BasicDBObject("wf_id", wfID).append("inputfile", inputFile);\r
+               doSubmit();\r
        }\r
 }\r
index 0a7be31c5e1aa768d2cf49e7f9583822962861d4..5a6e698d958df0a95857409a51cac5b1aece7c69 100644 (file)
@@ -1,5 +1,14 @@
---MEDIAFILE\r
-select mediaid from vw_mediafiles where mediafilecount = 1\r
+--Hamis LOWRES\r
+drop view vw_mediafiles_path\r
+create view vw_mediafiles_path as\r
+select relativepath, count(*) as count from mediafile where storeid=21 group by relativepath\r
+\r
+select * from mediafile mf, vw_mediafiles_path v where v.count > 1 and mf.RELATIVEPATH = v.RELATIVEPATH order by v.count, mf.relativepath, mf.id\r
+\r
+--MEDIAFILE\r
+select count(*) from vw_mediafiles where mediafilecount = 0\r
+\r
+select * from mediafile where relativepath = ''\r
 \r
 select * from mediafile f where f.mediaid in (select mediaid from vw_mediafiles where mediafilecount = 1)\r
 --delete from mediafile f where f.mediaid in (select mediaid from vw_mediafiles where mediafilecount = 1)\r
index 992b6297df1616f84801f5bab5c278ab9499055e..b0826fddacd9a4ec9b9d72b2e4daa7f97efe34c8 100644 (file)
        </servlet-mapping>\r
 \r
        <session-config>\r
-               <session-timeout>15</session-timeout>\r
+               <!-- percben -->\r
+               <session-timeout>60</session-timeout>\r
        </session-config>\r
+\r
        <welcome-file-list>\r
                <welcome-file>index.html</welcome-file>\r
                <welcome-file>index.htm</welcome-file>\r
                <welcome-file>index.zul</welcome-file>\r
                <welcome-file>index.zhtml</welcome-file>\r
        </welcome-file-list>\r
+\r
+       <security-constraint>\r
+               <web-resource-collection>\r
+                       <web-resource-name>Everything on the app</web-resource-name>\r
+                       <url-pattern>/*</url-pattern>\r
+               </web-resource-collection>\r
+               <user-data-constraint>\r
+                       <transport-guarantee>CONFIDENTIAL</transport-guarantee>\r
+               </user-data-constraint>\r
+       </security-constraint>\r
 </web-app>\r
index ae2934e9305ad6aae54e5e6f62680df6b1e8f9ea..8afaaab8223cc8058353eb1661e58562ab134b45 100644 (file)
@@ -10,6 +10,7 @@
            <timeout-message>Lejárt a munkamenet, kérem töltse be újra az alkalmazást.</timeout-message>\r
            <!-- timeout-uri>/timeout.zul</timeout-uri -->\r
            <automatic-timeout/>\r
+               <!-- masodpercben -->\r
 <!--       <session-timeout>900</session-timeout> -->\r
        </session-config>\r
 \r
index d850041d0d6d38fd04604d152d80a2c3c40972d0..4d20de8dbcd973c64efbabaa9c34effc6a953c40 100644 (file)
@@ -1,4 +1,4 @@
-version=2.3.7\r
+version=2.3.8\r
 footer=2016 © Copyright User Rendszerház Kft.\r
 \r
 login_info=Információ\r
index 17b95075e84e411908403fa34477b98b635e5dd4..0afd81fff635aacd1eaffda99c070e4591b4a46b 100644 (file)
@@ -1,6 +1,7 @@
 package user.jobengine.server.IT;\r
 \r
 import java.io.File;\r
+import java.io.IOException;\r
 import java.nio.charset.Charset;\r
 import java.nio.file.Files;\r
 import java.nio.file.Path;\r
@@ -15,12 +16,16 @@ import java.util.ArrayList;
 import java.util.Calendar;\r
 import java.util.Collections;\r
 import java.util.Date;\r
+import java.util.HashMap;\r
 import java.util.LinkedHashMap;\r
+import java.util.LinkedHashSet;\r
 import java.util.List;\r
 import java.util.Map;\r
+import java.util.Set;\r
 import java.util.function.Consumer;\r
 import java.util.stream.Stream;\r
 \r
+import org.apache.commons.lang.StringUtils;\r
 import org.apache.commons.lang.time.DateUtils;\r
 import org.junit.AfterClass;\r
 import org.junit.BeforeClass;\r
@@ -33,8 +38,10 @@ import com.ibm.nosql.json.api.DBCollection;
 import sqlj.runtime.ref.DefaultContext;\r
 import user.commons.CalendarUtils;\r
 import user.commons.IEntityBase;\r
+import user.commons.ListUtils;\r
 import user.commons.logging.LogUtils;\r
 import user.commons.nosql.NoSQLUtils;\r
+import user.commons.octopus.IOctopusAPI;\r
 import user.commons.octopus.OctopusAPI;\r
 import user.jobengine.db.IItemManager;\r
 import user.jobengine.db.IResultSetConsumer;\r
@@ -61,9 +68,12 @@ public class Support {
 \r
        @BeforeClass\r
        static public void setUpConnection() {\r
-               System.setProperty("jobengine.octopus.rundowns.name", "test_rundowns");\r
-               System.setProperty("jobengine.octopus.stories.name", "test_stories");\r
-               System.setProperty("jobengine.octopus.storyfolders.name", "test_storyfolders");\r
+               //              System.setProperty("jobengine.octopus.rundowns.name", "test_rundowns");\r
+               //              System.setProperty("jobengine.octopus.stories.name", "test_stories");\r
+               //              System.setProperty("jobengine.octopus.storyfolders.name", "test_storyfolders");\r
+               System.setProperty("jobengine.octopus.rundowns.name", "rundowns180608");\r
+               System.setProperty("jobengine.octopus.stories.name", "stories180608");\r
+               System.setProperty("jobengine.octopus.storyfolders.name", "storyfolders180608");\r
 \r
                System.setProperty("jobengine.nosql.db.url", "jdbc:db2://10.10.1.27:50000/mc:retrieveMessagesFromServerOnGetMessage=true;");\r
                System.setProperty("jobengine.nosql.db.user", "db2admin");\r
@@ -212,6 +222,61 @@ public class Support {
                return result;\r
        }\r
 \r
+       public Map<Media, List<String>> getExistingItemHouseIDs(String houseid) {\r
+               final Map<Media, List<String>> result = new HashMap<>();\r
+               final List<String> resultList = new ArrayList<>();\r
+               StringBuilder query = new StringBuilder();\r
+               query.append("select itemid, mediaid, replace(mediafilehouseid, concat('-', concat(itemhouseid,'.MXF')), '') filename");\r
+               query.append(" ");\r
+               query.append("from vw_items where replace(mediafilehouseid, concat('-', itemhouseid), '') != mediafilehouseid");\r
+               query.append(" ");\r
+               query.append("and replace(mediafilehouseid, concat('-', concat(itemhouseid,'.MXF')), '') = ?");\r
+               IStatementDecorator decorator = st -> {\r
+                       st.setString(1, houseid);\r
+               };\r
+               IResultSetConsumer consumer = rs -> {\r
+                       Media media = manager.getMedia(rs.getLong("mediaid"));\r
+\r
+                       if (result.size() == 0)\r
+                               result.put(media, resultList);\r
+\r
+                       Item item = manager.getItem(media.getItemId());\r
+                       resultList.add(item.getTitle());\r
+                       return true;\r
+               };\r
+               manager.executeQuery(query.toString(), consumer, decorator);\r
+               return result;\r
+       }\r
+\r
+       private Item getRundownItem(BasicDBObject rundown) {\r
+\r
+               StringBuilder query = new StringBuilder();\r
+               query.append("select id from item where title=?");\r
+               IStatementDecorator decorator = st -> {\r
+                       st.setString(1, getRundownTitle(rundown));\r
+               };\r
+               Item[] result = { null };\r
+               IResultSetConsumer consumer = rs -> {\r
+                       Item item = manager.getItem(rs.getLong("id"));\r
+                       result[0] = item;\r
+                       return false;\r
+               };\r
+               manager.executeQuery(query.toString(), consumer, decorator);\r
+               return result[0];\r
+       }\r
+\r
+       private String getRundownTitle(BasicDBObject rundown) {\r
+               String name = NoSQLUtils.asString(NoSQLUtils.asDBObject(rundown, IOctopusAPI.RUNDOWN_TYPE), IOctopusAPI.NAME);\r
+               if (StringUtils.isBlank(name))\r
+                       return null;\r
+               String channel = NoSQLUtils.asString(NoSQLUtils.asDBObject(rundown, IOctopusAPI.CHANNEL), IOctopusAPI.NAME);\r
+               Date scheduledStart = rundown.getDate(IOctopusAPI.SCHEDULED_START);\r
+               if (scheduledStart == null)\r
+                       return null;\r
+               String start = CalendarUtils.toString(CalendarUtils.createCalendar(scheduledStart), "yyyy.MM.dd HH:mm");\r
+               return String.format("%s %s %s", start, name, channel);\r
+       }\r
+\r
        private void processLowresDuplicateGroup(String fileName) {\r
                System.out.println("*** Processing: " + fileName);\r
                String query = "select mediafileid, mediafilehouseid, relativepath from vw_items_rd_lh where filename = ?";\r
@@ -326,4 +391,83 @@ public class Support {
                return result;\r
        }\r
 \r
+       @Test\r
+       public void repairRundownChunks() throws Exception {\r
+               OctopusAPI octopusAPI = new OctopusAPI();\r
+               Path sourcePath = Paths.get("c:\\Temp\\__");\r
+               final Set<String> names = new LinkedHashSet<>();\r
+\r
+               try (Stream<Path> pathStream = Files.walk(sourcePath)) {\r
+                       pathStream.forEach(new Consumer<Path>() {\r
+                               @Override\r
+                               public void accept(Path p) {\r
+                                       if (p.toFile().isDirectory())\r
+                                               return;\r
+                                       List<String> lines;\r
+                                       try {\r
+                                               lines = Files.readAllLines(p);\r
+                                               for (String line : lines) {\r
+                                                       if (!line.contains("clip archiválása sikertelen. A rendszer üzenete: null"))\r
+                                                               continue;\r
+                                                       String[] splittedLine = line.split("'");\r
+                                                       if (names.contains(splittedLine[1]))\r
+                                                               continue;\r
+                                                       names.add(splittedLine[1]);\r
+\r
+                                                       //lenyeli a duplikalt hozzadast, lekezelni. addig nem futtathato!!!!!!!\r
+                                                       Map<Media, List<String>> existing = getExistingItemHouseIDs(splittedLine[1]);\r
+\r
+                                                       Media media = (Media) existing.keySet().toArray()[0];\r
+                                                       List<String> itemTitles = (List<String>) existing.values().toArray()[0];\r
+                                                       List<BasicDBObject> rundowns = ListUtils.cast(octopusAPI.getRundownsByPlaceHolderID(splittedLine[1]));\r
+                                                       System.out.println(String.format("%s %d: ", splittedLine[1], media.getId()));\r
+\r
+                                                       for (BasicDBObject rd : rundowns) {\r
+                                                               String rundownTitle = getRundownTitle(rd);\r
+                                                               if (itemTitles.contains(rundownTitle) || rundownTitle.contains("00:00"))\r
+                                                                       continue;\r
+\r
+                                                               Item item = getRundownItem(rd);\r
+                                                               if (item == null) {\r
+                                                                       item = manager.createItem("Generic", rundownTitle, null, NoSQLUtils.asString(rd, IOctopusAPI.ID));\r
+                                                                       item.add();\r
+                                                                       System.out.print(String.format("* %s,", rundownTitle));\r
+                                                               } else {\r
+                                                                       System.out.print(String.format("%s (%d),", rundownTitle, item.getId()));\r
+                                                               }\r
+\r
+                                                               List<MediaFile> mediaFiles = media.getMediaFiles();\r
+                                                               if (mediaFiles != null) {\r
+                                                                       for (MediaFile mf : mediaFiles) {\r
+                                                                               mf.setId(0);\r
+                                                                               mf.setMediaId(0);\r
+                                                                       }\r
+                                                               }\r
+                                                               media.setId(0);\r
+                                                               media.setItemId(item.getId());\r
+                                                               media.setPersister(manager);\r
+                                                               media.add();\r
+\r
+                                                       }\r
+\r
+                                                       System.out.println();\r
+                                               }\r
+                                       } catch (IOException e) {\r
+                                               e.printStackTrace();\r
+                                       }\r
+                               }\r
+                       });\r
+               }\r
+\r
+               System.out.println(names.size());\r
+       }\r
+\r
+       @Test\r
+       public void test1() {\r
+               File sourceMediaFile = new File("c:/_downloads/mediacube-backlog-2018-05.pdf");\r
+               String sourceFileName = sourceMediaFile.getName();\r
+               String sourceFile = Paths.get("l:", sourceFileName).toString();\r
+               System.out.println(sourceFile);\r
+       }\r
+\r
 }\r