changeset 11231:06543fe1b967

8133841: Full HD video can not be played on standard 1080p screen in portrait mode Reviewed-by: kcr
author almatvee
date Mon, 08 Apr 2019 14:47:21 -0700
parents 7fc05179c7db
children ee34b53aac6b
files modules/javafx.media/src/main/native/gstreamer/gstreamer-lite/gstreamer/gst/gstregistry.c modules/javafx.media/src/main/native/gstreamer/plugins/avcdecoder/avcdecoder.c modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/Sink.cpp modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/Sink.h modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/dshowwrapper.cpp
diffstat 5 files changed, 147 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.media/src/main/native/gstreamer/gstreamer-lite/gstreamer/gst/gstregistry.c	Mon Apr 08 12:55:14 2019 -0700
+++ b/modules/javafx.media/src/main/native/gstreamer/gstreamer-lite/gstreamer/gst/gstregistry.c	Mon Apr 08 14:47:21 2019 -0700
@@ -1995,8 +1995,9 @@
 
 
   clear_scan_context (&context);
+
+  changed |= context.changed;
 #endif // GSTREAMER_LITE
-  changed |= context.changed;
 
   /* Remove cached plugins so stale info is cleared. */
   changed |= gst_registry_remove_cache_plugins (default_registry);
--- a/modules/javafx.media/src/main/native/gstreamer/plugins/avcdecoder/avcdecoder.c	Mon Apr 08 12:55:14 2019 -0700
+++ b/modules/javafx.media/src/main/native/gstreamer/plugins/avcdecoder/avcdecoder.c	Mon Apr 08 14:47:21 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -324,13 +324,20 @@
         size_t bytes_per_row = CVPixelBufferGetBytesPerRow(imageBuffer);
         if(!decode->is_stride_set)
         {
-            GstCaps *caps = gst_pad_get_current_caps(srcpad);
-            if (caps != NULL)
+            GstCaps *pad_caps = gst_pad_get_current_caps(srcpad);
+            if (pad_caps != NULL)
             {
-                GstStructure* caps_struct = gst_caps_get_structure(caps, 0);
-                gst_structure_set(caps_struct, "line_stride", G_TYPE_INT, (int)bytes_per_row, NULL);
-                decode->is_stride_set = TRUE;
-                gst_caps_unref(caps);
+                GstCaps *caps = gst_caps_copy(pad_caps);
+                if (caps != NULL)
+                {
+                    gst_caps_set_simple(caps, "line_stride", G_TYPE_INT, (int)bytes_per_row, NULL);
+                    GstEvent *caps_event = gst_event_new_caps(caps);
+                    if (caps_event != NULL)
+                        gst_pad_push_event(decode->srcpad, caps_event);
+                    decode->is_stride_set = TRUE;
+                    gst_caps_unref(caps);
+                }
+                gst_caps_unref(pad_caps);
             }
         }
         if (kCVReturnSuccess == CVPixelBufferLockBaseAddress (imageBuffer, 0))
--- a/modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/Sink.cpp	Mon Apr 08 12:55:14 2019 -0700
+++ b/modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/Sink.cpp	Mon Apr 08 14:47:21 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
     m_pIAlloc = NULL;
     m_pAlloc = NULL;
     m_bUseExternalAllocator = false;
+    m_bEnableDynamicFormatChanges = false;
 }
 
 CInputPin::~CInputPin()
@@ -152,6 +153,70 @@
     return S_OK;
 }
 
+HRESULT CInputPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
+{
+    HRESULT hr = CBasePin::ReceiveConnection(pConnector, pmt);
+    if (m_bEnableDynamicFormatChanges && hr == VFW_E_ALREADY_CONNECTED)
+    {
+        CAutoLock cObjectLock(m_pLock);
+
+        CMediaType *pcmt = (CMediaType*)pmt;
+        hr = CheckMediaType(pcmt);
+        if (hr == S_OK)
+        {
+            if (m_Connected != pConnector)
+            {
+                if (m_Connected != NULL)
+                {
+                    m_Connected->Release();
+                }
+                m_Connected = pConnector;
+                m_Connected->AddRef();
+            }
+
+            hr = SetMediaType(pcmt);
+            if (SUCCEEDED(hr))
+            {
+                if (IsEqualGUID(FORMAT_VideoInfo2, pcmt->formattype))
+                {
+                    VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pcmt->pbFormat;
+                    DWORD dwSize = vih2->bmiHeader.biSizeImage;
+                    if (dwSize > 0)
+                    {
+                        IMemAllocator *pAllocator = NULL;
+                        hr = GetAllocator(&pAllocator);
+                        if (SUCCEEDED(hr))
+                        {
+                            ALLOCATOR_PROPERTIES request;
+                            ZeroMemory(&request, sizeof(ALLOCATOR_PROPERTIES));
+                            hr = pAllocator->GetProperties(&request);
+                            if (SUCCEEDED(hr))
+                            {
+                                request.cbBuffer = dwSize;
+                                hr = pAllocator->Decommit();
+                                if (SUCCEEDED(hr))
+                                {
+                                    ALLOCATOR_PROPERTIES actual;
+                                    ZeroMemory(&actual, sizeof(ALLOCATOR_PROPERTIES));
+                                    hr = pAllocator->SetProperties(&request, &actual);
+                                    if (SUCCEEDED(hr))
+                                    {
+                                        hr = pAllocator->Commit();
+                                    }
+                                }
+                            }
+
+                            pAllocator->Release();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return hr;
+}
+
 CSink::CSink(HRESULT *phr) : CBaseRenderer(CLSID_Sink, "CSink", NULL, phr)
 {
     ZeroMemory(&m_UserData, sizeof(sUserData));
@@ -163,6 +228,7 @@
 
     m_bForceStereoOutput = false;
     m_bUseExternalAllocator = false;
+    m_bEnableDynamicFormatChanges = false;
 
     m_bEOSInProgress = false;
     m_bWorkerThreadExits = false;
@@ -276,10 +342,14 @@
 
                 if (SinkEventCallback != NULL)
                 {
-                    __int64 width = hdrout->rcSource.right;
-                    __int64 height = hdrout->rcSource.bottom;
-                    __int64 resolution = (width << 32) | height;
-                    SinkEventCallback(SINK_VIDEO_RESOLUTION, (void*)&resolution, sizeof(__int64), &m_UserData);
+                    sVideoResolutionEvent resolution;
+                    resolution.width = hdrout->rcSource.right;
+                    resolution.height = hdrout->rcSource.bottom;
+                    if (m_bEnableDynamicFormatChanges)
+                        resolution.offset = resolution.width;
+                    else
+                        resolution.offset = 1920;
+                    SinkEventCallback(SINK_VIDEO_RESOLUTION, (void*)&resolution, sizeof(sVideoResolutionEvent), &m_UserData);
                 }
             }
 
@@ -477,6 +547,7 @@
         }
 
         ((CInputPin*)m_pInputPin)->m_bUseExternalAllocator = m_bUseExternalAllocator;
+        ((CInputPin*)m_pInputPin)->m_bEnableDynamicFormatChanges = m_bEnableDynamicFormatChanges;
     }
 
     return m_pInputPin;
@@ -531,6 +602,9 @@
     m_bUseExternalAllocator = (pOutputFormat->bUseExternalAllocator != 0);
     if (m_pInputPin)
         ((CInputPin*)m_pInputPin)->m_bUseExternalAllocator = m_bUseExternalAllocator;
+    m_bEnableDynamicFormatChanges = (pOutputFormat->bEnableDynamicFormatChanges != 0);
+    if (m_pInputPin)
+        ((CInputPin*)m_pInputPin)->m_bEnableDynamicFormatChanges = m_bEnableDynamicFormatChanges;
 
     return S_OK;
 }
--- a/modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/Sink.h	Mon Apr 08 12:55:14 2019 -0700
+++ b/modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/Sink.h	Mon Apr 08 14:47:21 2019 -0700
@@ -48,6 +48,14 @@
     ULONG length;
     BOOL bForceStereoOutput;
     BOOL bUseExternalAllocator;
+    BOOL bEnableDynamicFormatChanges;
+};
+
+struct sVideoResolutionEvent
+{
+    int width;
+    int height;
+    int offset;
 };
 
 enum SINK_EVENTS
@@ -79,9 +87,11 @@
     HRESULT SetReleaseSampleCallback(void (*function)(GstBuffer *pBuffer, sUserData *pUserData));
     HRESULT SetGetGstBufferCallback(void (*function)(GstBuffer **ppBuffer, long lSize, sUserData *pUserData));
     HRESULT CreateAllocator();
+    HRESULT ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt);
 
 public:
     bool m_bUseExternalAllocator;
+    bool m_bEnableDynamicFormatChanges;
 
 private:
     CAllocator *m_pAlloc;
@@ -130,6 +140,7 @@
 
     bool m_bForceStereoOutput;
     bool m_bUseExternalAllocator;
+    bool m_bEnableDynamicFormatChanges;
 
     bool m_bEOSInProgress;
     bool m_bWorkerThreadExits;
--- a/modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/dshowwrapper.cpp	Mon Apr 08 12:55:14 2019 -0700
+++ b/modules/javafx.media/src/main/native/gstreamer/plugins/dshowwrapper/dshowwrapper.cpp	Mon Apr 08 14:47:21 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -754,43 +754,43 @@
             if (decoder->eOutputFormat[pUserData->output_index] == MEDIA_FORMAT_VIDEO_H264)
             {
                 if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                    g_print("AMDEBUG MP2T H264 %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
+                    g_print("JFXMEDIA MP2T H264 %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
                 else if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && !GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                    g_print("AMDEBUG MP2T H264 %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
+                    g_print("DEBUG MP2T H264 %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
                 else
-                    g_print("AMDEBUG MP2T H264 -1\n");
+                    g_print("JFXMEDIA MP2T H264 -1\n");
             }
             if (decoder->eOutputFormat[pUserData->output_index] == MEDIA_FORMAT_AUDIO_AAC)
             {
                 if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                    g_print("AMDEBUG MP2T AAC  %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
+                    g_print("JFXMEDIA MP2T AAC  %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
                 else if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && !GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                    g_print("AMDEBUG MP2T AAC  %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
+                    g_print("JFXMEDIA MP2T AAC  %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
                 else
-                    g_print("AMDEBUG MP2T AAC  -1\n");
+                    g_print("JFXMEDIA MP2T AAC  -1\n");
             }
         }
 #endif
 #if H264_PTS_DEBUG
-        if (decoder->eInputFormat == MEDIA_FORMAT_VIDEO_H264)
+        if (decoder->eInputFormat == MEDIA_FORMAT_VIDEO_H264 || decoder->eInputFormat == MEDIA_FORMAT_VIDEO_AVC1)
         {
             if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                g_print("AMDEBUG H264 %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
+                g_print("JFXMEDIA H264 %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
             else if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && !GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                g_print("AMDEBUG H264 %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
+                g_print("JFXMEDIA H264 %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
             else
-                g_print("AMDEBUG H264 -1\n");
+                g_print("JFXMEDIA H264 -1\n");
         }
 #endif
 #if AAC_PTS_DEBUG
         if (decoder->eInputFormat == MEDIA_FORMAT_AUDIO_AAC)
         {
             if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                g_print("AMDEBUG AAC  %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
+                g_print("JFXMEDIA AAC  %I64u %I64u\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]), GST_BUFFER_DURATION(decoder->out_buffer[pUserData->output_index]));
             else if (GST_BUFFER_TIMESTAMP_IS_VALID(decoder->out_buffer[pUserData->output_index]) && !GST_BUFFER_DURATION_IS_VALID(decoder->out_buffer[pUserData->output_index]))
-                g_print("AMDEBUG AAC  %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
+                g_print("JFXMEDIA AAC  %I64u -1\n", GST_BUFFER_TIMESTAMP(decoder->out_buffer[pUserData->output_index]));
             else
-                g_print("AMDEBUG AAC  -1\n");
+                g_print("JFXMEDIA AAC  -1\n");
         }
 #endif
 
@@ -875,13 +875,13 @@
         decoder->is_eos[pUserData->output_index] = TRUE;
 #if EOS_DEBUG
         if (decoder->eInputFormat == MEDIA_FORMAT_STREAM_MP2T && (decoder->eOutputFormat[pUserData->output_index] == MEDIA_FORMAT_VIDEO_AVC1 || decoder->eOutputFormat[pUserData->output_index] == MEDIA_FORMAT_VIDEO_H264))
-            g_print("AMDEBUG EOS MP2T H264\n");
+            g_print("JFXMEDIA EOS MP2T H264\n");
         else if (decoder->eInputFormat == MEDIA_FORMAT_STREAM_MP2T && decoder->eOutputFormat[pUserData->output_index] == MEDIA_FORMAT_AUDIO_AAC)
-            g_print("AMDEBUG EOS MP2T AAC\n");
+            g_print("JFXMEDIA EOS MP2T AAC\n");
         else if (decoder->eInputFormat == MEDIA_FORMAT_VIDEO_AVC1 || decoder->eInputFormat == MEDIA_FORMAT_VIDEO_H264)
-            g_print("AMDEBUG EOS H264\n");
+            g_print("JFXMEDIA EOS H264\n");
         else if (decoder->eInputFormat == MEDIA_FORMAT_AUDIO_AAC)
-            g_print("AMDEBUG EOS AAC\n");
+            g_print("JFXMEDIA EOS AAC\n");
 #endif
         gst_pad_push_event (decoder->srcpad[pUserData->output_index], gst_event_new_eos());
         break;
@@ -947,11 +947,12 @@
         }
         break;
     case SINK_VIDEO_RESOLUTION:
-        if (pData != NULL && size == sizeof(__int64))
+        if (pData != NULL && size == sizeof(sVideoResolutionEvent))
         {
-            __int64 resolution = *((__int64*)pData);
-            int width = (resolution >> 32) & 0x00000000FFFFFFFF;
-            int height = resolution & 0x00000000FFFFFFFF;
+            sVideoResolutionEvent resolution = *((sVideoResolutionEvent*)pData);
+            int width = resolution.width;
+            int height = resolution.height;
+            int offset = resolution.offset;
 
             GstCaps *padCaps = gst_pad_get_current_caps(decoder->srcpad[pUserData->output_index]);
             if (padCaps == NULL)
@@ -966,11 +967,11 @@
                     "width", G_TYPE_INT, width,
                     "height", G_TYPE_INT, height,
                     "offset-y", G_TYPE_INT, 0,
-                    "offset-v", G_TYPE_INT, (1920*height+((1920*height)/4)),
-                    "offset-u", G_TYPE_INT, 1920*height,
-                    "stride-y", G_TYPE_INT, 1920,
-                    "stride-v", G_TYPE_INT, 1920/2,
-                    "stride-u", G_TYPE_INT, 1920/2,
+                    "offset-v", G_TYPE_INT, (offset*height+((offset*height)/4)),
+                    "offset-u", G_TYPE_INT, offset*height,
+                    "stride-y", G_TYPE_INT, offset,
+                    "stride-v", G_TYPE_INT, offset/2,
+                    "stride-u", G_TYPE_INT, offset/2,
                     NULL);
             }
             else if (decoder->eOutputFormat[DEFAULT_OUTPUT_DS_STREAM_INDEX] == MEDIA_FORMAT_VIDEO_YV12)
@@ -1944,6 +1945,10 @@
     sInputFormat inputFormat;
     ZeroMemory(&inputFormat, sizeof(sInputFormat));
 
+    // Init output
+    sOutputFormat outputFormat;
+    ZeroMemory(&outputFormat, sizeof(sOutputFormat));
+
     gint width = 0;
     gint height = 0;
     const GValue *v = NULL;
@@ -2022,6 +2027,15 @@
         pbFormat->dwFlags = lengthSizeMinusOne + 1;
         memcpy(pbFormat->dwSequenceHeader, header, header_size);
         pbFormat->cbSequenceHeader = header_size;
+
+        // Enable dynamic format change for MP4 via ReceiveConnection().
+        // HLS works fine using QueryAccept without buffer size changes and
+        // breaks if dynamic format is enabled, so for now we will use it only
+        // for MP4. It seems we only need it for portrait video or anything
+        // bigger then 1920x1080, so we will enable it only for such resolution.
+        // See JDK-8133841.
+        if ((width < height) || (width > 1920 && height > 1080))
+            outputFormat.bEnableDynamicFormatChanges = 1;
     }
     else
     {
@@ -2060,10 +2074,6 @@
     if (!dshowwrapper_create_ds_source(decoder, &inputFormat))
         goto exit;
 
-    // Init output
-    sOutputFormat outputFormat;
-    ZeroMemory(&outputFormat, sizeof(sOutputFormat));
-
     gint framerate_num = 0;
     gint framerate_den = 0;