improving the panoramic video check, do not rely on 2:1 aspect ratio
This commit is contained in:
parent
eba2464bc7
commit
6d0c5fdf65
3 changed files with 95 additions and 2 deletions
|
@ -48,7 +48,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:5.2.13'
|
||||
implementation 'com.simplemobiletools:commons:5.2.14'
|
||||
implementation 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
|
||||
implementation 'androidx.multidex:multidex:2.0.0'
|
||||
implementation 'it.sephiroth.android.exif:library:1.0.1'
|
||||
|
|
|
@ -36,9 +36,13 @@ import com.simplemobiletools.gallery.views.MediaSideScroll
|
|||
import kotlinx.android.synthetic.main.bottom_video_time_holder.view.*
|
||||
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(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener {
|
||||
private val PROGRESS = "progress"
|
||||
private val FILE_CHANNEL_CONTAINERS = arrayListOf("moov", "trak", "mdia", "minf", "udta", "stbl")
|
||||
|
||||
private var mTextureView: TextureView? = null
|
||||
private var mCurrTimeView: TextView? = null
|
||||
|
@ -112,10 +116,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
|
||||
mIsFullscreen = activity!!.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
initTimeHolder()
|
||||
checkIfPanorama()
|
||||
|
||||
medium.path.getVideoResolution()?.apply {
|
||||
mVideoSize.x = x
|
||||
mVideoSize.y = y
|
||||
mIsPanorama = x == y * 2
|
||||
if (mIsPanorama) {
|
||||
mView.apply {
|
||||
panorama_outline.beVisible()
|
||||
|
@ -628,6 +633,67 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S
|
|||
mIsDragged = false
|
||||
}
|
||||
|
||||
private fun checkIfPanorama() {
|
||||
try {
|
||||
val fis = FileInputStream(File(medium.path))
|
||||
parseFileChannel(fis.channel, 0, 0, 0)
|
||||
} 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
|
||||
}
|
||||
}
|
||||
mIsPanorama = sb.toString().contains("<GSpherical:Spherical>true") || sb.toString().contains("GSpherical:Spherical=\"True\"")
|
||||
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)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.simplemobiletools.gallery.helpers
|
||||
|
||||
import java.io.UnsupportedEncodingException
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.charset.Charset
|
||||
|
||||
// file taken from the https://github.com/sannies/mp4parser project, used at determining if a video is a panoramic one
|
||||
object IsoTypeReader {
|
||||
fun readUInt32(bb: ByteBuffer): Long {
|
||||
var i = bb.int.toLong()
|
||||
if (i < 0) {
|
||||
i += 1L shl 32
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
fun read4cc(bb: ByteBuffer): String? {
|
||||
val codeBytes = ByteArray(4)
|
||||
bb.get(codeBytes)
|
||||
|
||||
return try {
|
||||
String(codeBytes, Charset.forName("ISO-8859-1"))
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue