improving the panoramic video check, do not rely on 2:1 aspect ratio

This commit is contained in:
tibbi 2018-10-30 19:19:32 +01:00
parent eba2464bc7
commit 6d0c5fdf65
3 changed files with 95 additions and 2 deletions

View file

@ -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'

View file

@ -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)

View file

@ -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
}
}
}