mirror of
				https://github.com/SimpleMobileTools/Simple-Gallery.git
				synced 2025-06-05 21:59:19 +02:00 
			
		
		
		
	improve panorama video handling at third party intents
This commit is contained in:
		| @@ -27,6 +27,7 @@ import com.simplemobiletools.gallery.pro.models.Medium | ||||
| import kotlinx.android.synthetic.main.bottom_actions.* | ||||
| import kotlinx.android.synthetic.main.fragment_holder.* | ||||
| import java.io.File | ||||
| import java.io.FileInputStream | ||||
|  | ||||
| open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentListener { | ||||
|  | ||||
| @@ -147,10 +148,30 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         val mimeType = getUriMimeType(mUri.toString(), newUri) | ||||
|         Intent(this, VideoPlayerActivity::class.java).apply { | ||||
|             setDataAndType(newUri, mimeType) | ||||
|             startActivity(this) | ||||
|         var isPanorama = false | ||||
|         val realPath = intent?.extras?.getString(REAL_FILE_PATH) ?: "" | ||||
|         try { | ||||
|             if (realPath.isNotEmpty()) { | ||||
|                 val fis = FileInputStream(File(realPath)) | ||||
|                 parseFileChannel(realPath, fis.channel, 0, 0, 0) { | ||||
|                     isPanorama = true | ||||
|                 } | ||||
|             } | ||||
|         } catch (ignored: Exception) { | ||||
|         } catch (ignored: OutOfMemoryError) { | ||||
|         } | ||||
|  | ||||
|         if (isPanorama) { | ||||
|             Intent(applicationContext, PanoramaVideoActivity::class.java).apply { | ||||
|                 putExtra(PATH, realPath) | ||||
|                 startActivity(this) | ||||
|             } | ||||
|         } else { | ||||
|             val mimeType = getUriMimeType(mUri.toString(), newUri) | ||||
|             Intent(applicationContext, VideoPlayerActivity::class.java).apply { | ||||
|                 setDataAndType(newUri, mimeType) | ||||
|                 startActivity(this) | ||||
|             } | ||||
|         } | ||||
|         finish() | ||||
|     } | ||||
|   | ||||
| @@ -35,6 +35,9 @@ import com.simplemobiletools.gallery.pro.svg.SvgSoftwareLayerSetter | ||||
| import com.simplemobiletools.gallery.pro.views.MySquareImageView | ||||
| import pl.droidsonroids.gif.GifDrawable | ||||
| import java.io.File | ||||
| import java.io.FileInputStream | ||||
| import java.nio.ByteBuffer | ||||
| import java.nio.channels.FileChannel | ||||
| import java.util.HashSet | ||||
| import java.util.LinkedHashSet | ||||
| import kotlin.Comparator | ||||
| @@ -623,3 +626,60 @@ fun Context.updateWidgets() { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // based on https://github.com/sannies/mp4parser/blob/master/examples/src/main/java/com/google/code/mp4parser/example/PrintStructure.java | ||||
| fun Context.parseFileChannel(path: String, fc: FileChannel, level: Int, start: Long, end: Long, callback: () -> Unit) { | ||||
|     val FILE_CHANNEL_CONTAINERS = arrayListOf("moov", "trak", "mdia", "minf", "udta", "stbl") | ||||
|     try { | ||||
|         var iteration = 0 | ||||
|         var currEnd = end | ||||
|         fc.position(start) | ||||
|         if (currEnd <= 0) { | ||||
|             currEnd = start + fc.size() | ||||
|         } | ||||
|  | ||||
|         while (currEnd - fc.position() > 8) { | ||||
|             // just a check to avoid deadloop at some videos | ||||
|             if (iteration++ > 50) { | ||||
|                 return | ||||
|             } | ||||
|  | ||||
|             val begin = fc.position() | ||||
|             val byteBuffer = ByteBuffer.allocate(8) | ||||
|             fc.read(byteBuffer) | ||||
|             byteBuffer.rewind() | ||||
|             val size = IsoTypeReader.readUInt32(byteBuffer) | ||||
|             val type = IsoTypeReader.read4cc(byteBuffer) | ||||
|             val newEnd = begin + size | ||||
|  | ||||
|             if (type == "uuid") { | ||||
|                 val fis = FileInputStream(File(path)) | ||||
|                 fis.skip(begin) | ||||
|  | ||||
|                 val sb = StringBuilder() | ||||
|                 val buffer = ByteArray(1024) | ||||
|                 while (true) { | ||||
|                     val n = fis.read(buffer) | ||||
|                     if (n != -1) { | ||||
|                         sb.append(String(buffer, 0, n)) | ||||
|                     } else { | ||||
|                         break | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 val xmlString = sb.toString().toLowerCase() | ||||
|                 if (xmlString.contains("gspherical:projectiontype>equirectangular") || xmlString.contains("gspherical:projectiontype=\"equirectangular\"")) { | ||||
|                     callback.invoke() | ||||
|                 } | ||||
|                 return | ||||
|             } | ||||
|  | ||||
|             if (FILE_CHANNEL_CONTAINERS.contains(type)) { | ||||
|                 parseFileChannel(path, fc, level + 1, begin + 8, newEnd, callback) | ||||
|             } | ||||
|  | ||||
|             fc.position(newEnd) | ||||
|         } | ||||
|     } catch (ignored: Exception) { | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,6 @@ import com.simplemobiletools.commons.extensions.* | ||||
| import com.simplemobiletools.gallery.pro.R | ||||
| import com.simplemobiletools.gallery.pro.activities.PanoramaVideoActivity | ||||
| import com.simplemobiletools.gallery.pro.extensions.* | ||||
| import com.simplemobiletools.gallery.pro.helpers.IsoTypeReader | ||||
| import com.simplemobiletools.gallery.pro.helpers.MEDIUM | ||||
| import com.simplemobiletools.gallery.pro.helpers.PATH | ||||
| import com.simplemobiletools.gallery.pro.models.Medium | ||||
| @@ -19,12 +18,8 @@ import com.simplemobiletools.gallery.pro.views.MediaSideScroll | ||||
| import kotlinx.android.synthetic.main.pager_video_item.view.* | ||||
| import java.io.File | ||||
| import java.io.FileInputStream | ||||
| import java.nio.ByteBuffer | ||||
| import java.nio.channels.FileChannel | ||||
|  | ||||
| class VideoFragment : ViewPagerFragment() { | ||||
|     private val FILE_CHANNEL_CONTAINERS = arrayListOf("moov", "trak", "mdia", "minf", "udta", "stbl") | ||||
|  | ||||
|     private var mIsFullscreen = false | ||||
|     private var mWasFragmentInit = false | ||||
|     private var mIsPanorama = false | ||||
| @@ -168,67 +163,14 @@ class VideoFragment : ViewPagerFragment() { | ||||
|     private fun checkIfPanorama() { | ||||
|         try { | ||||
|             val fis = FileInputStream(File(medium.path)) | ||||
|             parseFileChannel(fis.channel, 0, 0, 0) | ||||
|             context!!.parseFileChannel(medium.path, fis.channel, 0, 0, 0) { | ||||
|                 mIsPanorama = true | ||||
|             } | ||||
|         } catch (ignored: Exception) { | ||||
|         } catch (ignored: OutOfMemoryError) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // based on https://github.com/sannies/mp4parser/blob/master/examples/src/main/java/com/google/code/mp4parser/example/PrintStructure.java | ||||
|     private fun parseFileChannel(fc: FileChannel, level: Int, start: Long, end: Long) { | ||||
|         try { | ||||
|             var iteration = 0 | ||||
|             var currEnd = end | ||||
|             fc.position(start) | ||||
|             if (currEnd <= 0) { | ||||
|                 currEnd = start + fc.size() | ||||
|             } | ||||
|  | ||||
|             while (currEnd - fc.position() > 8) { | ||||
|                 // just a check to avoid deadloop at some videos | ||||
|                 if (iteration++ > 50) { | ||||
|                     return | ||||
|                 } | ||||
|  | ||||
|                 val begin = fc.position() | ||||
|                 val byteBuffer = ByteBuffer.allocate(8) | ||||
|                 fc.read(byteBuffer) | ||||
|                 byteBuffer.rewind() | ||||
|                 val size = IsoTypeReader.readUInt32(byteBuffer) | ||||
|                 val type = IsoTypeReader.read4cc(byteBuffer) | ||||
|                 val newEnd = begin + size | ||||
|  | ||||
|                 if (type == "uuid") { | ||||
|                     val fis = FileInputStream(File(medium.path)) | ||||
|                     fis.skip(begin) | ||||
|  | ||||
|                     val sb = StringBuilder() | ||||
|                     val buffer = ByteArray(1024) | ||||
|                     while (true) { | ||||
|                         val n = fis.read(buffer) | ||||
|                         if (n != -1) { | ||||
|                             sb.append(String(buffer, 0, n)) | ||||
|                         } else { | ||||
|                             break | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     val xmlString = sb.toString().toLowerCase() | ||||
|                     mIsPanorama = xmlString.contains("gspherical:projectiontype>equirectangular") || | ||||
|                             xmlString.contains("gspherical:projectiontype=\"equirectangular\"") | ||||
|                     return | ||||
|                 } | ||||
|  | ||||
|                 if (FILE_CHANNEL_CONTAINERS.contains(type)) { | ||||
|                     parseFileChannel(fc, level + 1, begin + 8, newEnd) | ||||
|                 } | ||||
|  | ||||
|                 fc.position(newEnd) | ||||
|             } | ||||
|         } catch (ignored: Exception) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun openPanorama() { | ||||
|         Intent(context, PanoramaVideoActivity::class.java).apply { | ||||
|             putExtra(PATH, medium.path) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user