|  |  | @ -1,25 +1,29 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | package com.frank.ffmpeg.activity |  |  |  | package com.frank.ffmpeg.activity | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.annotation.SuppressLint |  |  |  | import android.annotation.SuppressLint | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import android.graphics.Bitmap | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.os.Bundle |  |  |  | import android.os.Bundle | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.os.Handler |  |  |  | import android.os.Handler | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.os.Message |  |  |  | import android.os.Message | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.text.TextUtils |  |  |  | import android.util.Log | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | import android.view.View |  |  |  | import android.view.View | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import android.widget.ImageView | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.widget.ProgressBar |  |  |  | import android.widget.ProgressBar | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.widget.RelativeLayout |  |  |  | import android.widget.RelativeLayout | 
			
		
	
		
		
			
				
					
					|  |  |  | import android.widget.TextView |  |  |  | import android.widget.TextView | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.R |  |  |  | import com.frank.ffmpeg.R | 
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.handler.FFmpegHandler |  |  |  | import com.frank.ffmpeg.handler.FFmpegHandler | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | import com.frank.ffmpeg.handler.FFmpegHandler.* | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.model.MediaBean |  |  |  | import com.frank.ffmpeg.model.MediaBean | 
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.tool.JsonParseTool |  |  |  | import com.frank.ffmpeg.tool.JsonParseTool | 
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.util.FFmpegUtil |  |  |  | import com.frank.ffmpeg.util.FFmpegUtil | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.util.FileUtil |  |  |  | import com.frank.ffmpeg.util.FileUtil | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.handler.FFmpegHandler.MSG_BEGIN |  |  |  | import com.frank.ffmpeg.metadata.FFmpegMediaRetriever | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | import com.frank.ffmpeg.handler.FFmpegHandler.MSG_FINISH |  |  |  | import java.lang.StringBuilder | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /** |  |  |  | /** | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Using ffprobe to parse media format data |  |  |  |  * Using ffprobe to parse media format data | 
			
		
	
	
		
		
			
				
					|  |  | @ -33,6 +37,10 @@ class ProbeFormatActivity : BaseActivity() { | 
			
		
	
		
		
			
				
					
					|  |  |  |     private var layoutProbe: RelativeLayout? = null |  |  |  |     private var layoutProbe: RelativeLayout? = null | 
			
		
	
		
		
			
				
					
					|  |  |  |     private var ffmpegHandler: FFmpegHandler? = null |  |  |  |     private var ffmpegHandler: FFmpegHandler? = null | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private var view: View? = null | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private val MSG_FRAME = 9099 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     @SuppressLint("HandlerLeak") |  |  |  |     @SuppressLint("HandlerLeak") | 
			
		
	
		
		
			
				
					
					|  |  |  |     private val mHandler = object : Handler() { |  |  |  |     private val mHandler = object : Handler() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         override fun handleMessage(msg: Message) { |  |  |  |         override fun handleMessage(msg: Message) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -47,12 +55,22 @@ class ProbeFormatActivity : BaseActivity() { | 
			
		
	
		
		
			
				
					
					|  |  |  |                     layoutProbe!!.visibility = View.VISIBLE |  |  |  |                     layoutProbe!!.visibility = View.VISIBLE | 
			
		
	
		
		
			
				
					
					|  |  |  |                     val result = msg.obj?: msg.obj |  |  |  |                     val result = msg.obj?: msg.obj | 
			
		
	
		
		
			
				
					
					|  |  |  |                     if (result != null) { |  |  |  |                     if (result != null) { | 
			
		
	
		
		
			
				
					
					|  |  |  |                         val resultFormat = JsonParseTool.stringFormat(result as MediaBean) |  |  |  |                         val mediaInfo = JsonParseTool.stringFormat(result as MediaBean) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                         if (!TextUtils.isEmpty(resultFormat) && txtProbeFormat != null) { |  |  |  |                         if (!mediaInfo.isNullOrEmpty() && txtProbeFormat != null) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                             txtProbeFormat!!.text = resultFormat |  |  |  |                             txtProbeFormat!!.text = mediaInfo | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                         } |  |  |  |                         } | 
			
		
	
		
		
			
				
					
					|  |  |  |                     } |  |  |  |                     } | 
			
		
	
		
		
			
				
					
					|  |  |  |                 } |  |  |  |                 } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 MSG_INFO -> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     val mediaInfo = msg.obj as String | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     if (!mediaInfo.isNullOrEmpty()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                         txtProbeFormat!!.text = mediaInfo | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 MSG_FRAME -> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     val bitmap = msg.obj as Bitmap | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     findViewById<ImageView>(R.id.img_frame).setImageBitmap(bitmap) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 } | 
			
		
	
		
		
			
				
					
					|  |  |  |                 else -> { |  |  |  |                 else -> { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 } |  |  |  |                 } | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
	
		
		
			
				
					|  |  | @ -73,15 +91,27 @@ class ProbeFormatActivity : BaseActivity() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         progressProbe = getView(R.id.progress_probe) |  |  |  |         progressProbe = getView(R.id.progress_probe) | 
			
		
	
		
		
			
				
					
					|  |  |  |         layoutProbe = getView(R.id.layout_probe) |  |  |  |         layoutProbe = getView(R.id.layout_probe) | 
			
		
	
		
		
			
				
					
					|  |  |  |         initViewsWithClick(R.id.btn_probe_format) |  |  |  |         initViewsWithClick(R.id.btn_probe_format) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         initViewsWithClick(R.id.btn_retrieve_format) | 
			
		
	
		
		
			
				
					
					|  |  |  |         txtProbeFormat = getView(R.id.txt_probe_format) |  |  |  |         txtProbeFormat = getView(R.id.txt_probe_format) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     override fun onViewClick(view: View) { |  |  |  |     override fun onViewClick(view: View) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         this.view = view | 
			
		
	
		
		
			
				
					
					|  |  |  |         selectFile() |  |  |  |         selectFile() | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     override fun onSelectedFile(filePath: String) { |  |  |  |     override fun onSelectedFile(filePath: String) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         doHandleProbe(filePath) |  |  |  | 
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         when (view?.id) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             R.id.btn_probe_format -> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 doHandleProbe(filePath) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             R.id.btn_retrieve_format -> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 Thread {retrieveMediaMetadata(filePath)}.start() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             else -> { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     /** |  |  |  |     /** | 
			
		
	
	
		
		
			
				
					|  |  | @ -104,4 +134,62 @@ class ProbeFormatActivity : BaseActivity() { | 
			
		
	
		
		
			
				
					
					|  |  |  |         mHandler.removeCallbacksAndMessages(null) |  |  |  |         mHandler.removeCallbacksAndMessages(null) | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     private fun retrieveMediaMetadata(path :String) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         if (path.isEmpty()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             return | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         try { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val resultBuilder = StringBuilder() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val retriever = FFmpegMediaRetriever() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             retriever.setDataSource(path) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val duration = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_DURATION) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (duration != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("duration:$duration\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val audioCodec = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_AUDIO_CODEC) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (audioCodec != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("audioCodec:$audioCodec\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val videoCodec = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_VIDEO_CODEC) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (videoCodec != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("videoCodec:$videoCodec\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val width = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_VIDEO_WIDTH) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val height = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_VIDEO_HEIGHT) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (width != null && height != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("resolution:$width x $height\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val frameRate = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_FRAME_RATE) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (frameRate != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("frameRate:$frameRate\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val sampleRate = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_SAMPLE_RATE) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (sampleRate != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("sampleRate:$sampleRate\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val channelCount = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_CHANNEL_COUNT) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (channelCount != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("channelCount:$channelCount\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val channelLayout = retriever.extractMetadata(FFmpegMediaRetriever.METADATA_KEY_CHANNEL_LAYOUT) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (channelLayout != null) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 resultBuilder.append("channelLayout:$channelLayout\n") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             mHandler.obtainMessage(MSG_INFO, resultBuilder.toString()).sendToTarget() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             // Retrieve frame with timeUs | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             val bitmap = retriever.getFrameAtTime(5 * 1000000) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             if (bitmap != null) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 Log.e("FFmpegRetriever", "bitmap width=${bitmap.width}--height=${bitmap.height}") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 mHandler.obtainMessage(MSG_FRAME, bitmap).sendToTarget() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             retriever.release() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } catch (e : Exception) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             Log.e("FFmpegRetriever", "ffmpeg error=$e") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | 
 |