Add: FFmpegMediaRetriever usage

pull/209/head
xufulong 3 years ago
parent bc6eca53e8
commit dd09704876
  1. 20
      app/src/main/cpp/metadata/ffmpeg_media_retriever.c
  2. 1
      app/src/main/java/com/frank/ffmpeg/activity/MainActivity.kt
  3. 100
      app/src/main/java/com/frank/ffmpeg/activity/ProbeFormatActivity.kt
  4. 24
      app/src/main/res/layout/activity_probe.xml
  5. 3
      app/src/main/res/values-en/strings.xml
  6. 3
      app/src/main/res/values/strings.xml

@ -49,8 +49,8 @@ int get_scaled_context(State *s, AVCodecContext *pCodecCtx, int width, int heigh
s->scaled_codecCtx->pix_fmt = TARGET_IMAGE_FORMAT;
s->scaled_codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
s->scaled_codecCtx->bit_rate = codecP->bit_rate;
s->scaled_codecCtx->time_base.num = s->video_st->codec->time_base.num;
s->scaled_codecCtx->time_base.den = s->video_st->codec->time_base.den;
s->scaled_codecCtx->time_base.num = pCodecCtx->time_base.num;
s->scaled_codecCtx->time_base.den = pCodecCtx->time_base.den;
if (!targetCodec || avcodec_open2(s->scaled_codecCtx, targetCodec, NULL) < 0) {
LOGE("avcodec_open2() failed\n");
@ -490,7 +490,6 @@ int get_embedded_picture(State **state_ptr, AVPacket *pkt) {
int i = 0;
int got_packet = 0;
AVFrame *frame = NULL;
State *state = *state_ptr;
if (!state || !state->pFormatCtx) {
@ -520,8 +519,9 @@ int get_embedded_picture(State **state_ptr, AVPacket *pkt) {
break;
}
avcodec_send_packet(state->video_st->codec, pkt);
int ret = avcodec_receive_frame(state->video_st->codec, frame);
AVCodecContext *pCodecContext = state->video_st->codec;
avcodec_send_packet(pCodecContext, pkt);
int ret = avcodec_receive_frame(pCodecContext, frame);
if (ret == 0) {
got_frame = 1;
} else {
@ -534,7 +534,7 @@ int get_embedded_picture(State **state_ptr, AVPacket *pkt) {
convertedPkt.size = 0;
convertedPkt.data = NULL;
convert_image(state, state->video_st->codec, frame, &convertedPkt, &got_packet, -1, -1);
convert_image(state, pCodecContext, frame, &convertedPkt, &got_packet, -1, -1);
av_packet_unref(pkt);
av_init_packet(pkt);
@ -556,7 +556,6 @@ int get_embedded_picture(State **state_ptr, AVPacket *pkt) {
}
av_frame_free(&frame);
if (got_packet) {
return SUCCESS;
} else {
@ -579,8 +578,9 @@ void decode_frame(State *state, AVPacket *pkt, int *got_frame, int64_t desired_f
if (!is_supported_format(codec_id, pix_fmt)) {
*got_frame = 0;
avcodec_send_packet(state->video_st->codec, pkt);
int ret = avcodec_receive_frame(state->video_st->codec, frame);
AVCodecContext *pCodecContext = state->video_st->codec;
avcodec_send_packet(pCodecContext, pkt);
int ret = avcodec_receive_frame(pCodecContext, frame);
if (ret == 0) {
*got_frame = 1;
} else {
@ -593,7 +593,7 @@ void decode_frame(State *state, AVPacket *pkt, int *got_frame, int64_t desired_f
av_packet_unref(pkt);
}
av_init_packet(pkt);
convert_image(state, state->video_st->codec, frame, pkt, got_frame, width, height);
convert_image(state, pCodecContext, frame, pkt, got_frame, width, height);
break;
}
} else {

@ -71,7 +71,6 @@ class MainActivity : BaseActivity() {
-> intent.setClass(this@MainActivity, ProbeFormatActivity::class.java)
8 //audio effect
-> intent.setClass(this@MainActivity, AudioEffectActivity::class.java)
// -> intent.setClass(this@MainActivity, MediaPlayerActivity::class.java)
else -> {
}
}

@ -1,25 +1,29 @@
package com.frank.ffmpeg.activity
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.TextView
import com.frank.ffmpeg.R
import com.frank.ffmpeg.handler.FFmpegHandler
import com.frank.ffmpeg.handler.FFmpegHandler.*
import com.frank.ffmpeg.model.MediaBean
import com.frank.ffmpeg.tool.JsonParseTool
import com.frank.ffmpeg.util.FFmpegUtil
import com.frank.ffmpeg.util.FileUtil
import com.frank.ffmpeg.handler.FFmpegHandler.MSG_BEGIN
import com.frank.ffmpeg.handler.FFmpegHandler.MSG_FINISH
import com.frank.ffmpeg.metadata.FFmpegMediaRetriever
import java.lang.StringBuilder
/**
* Using ffprobe to parse media format data
@ -33,6 +37,10 @@ class ProbeFormatActivity : BaseActivity() {
private var layoutProbe: RelativeLayout? = null
private var ffmpegHandler: FFmpegHandler? = null
private var view: View? = null
private val MSG_FRAME = 9099
@SuppressLint("HandlerLeak")
private val mHandler = object : Handler() {
override fun handleMessage(msg: Message) {
@ -47,11 +55,21 @@ class ProbeFormatActivity : BaseActivity() {
layoutProbe!!.visibility = View.VISIBLE
val result = msg.obj?: msg.obj
if (result != null) {
val resultFormat = JsonParseTool.stringFormat(result as MediaBean)
if (!TextUtils.isEmpty(resultFormat) && txtProbeFormat != null) {
txtProbeFormat!!.text = resultFormat
val mediaInfo = JsonParseTool.stringFormat(result as MediaBean)
if (!mediaInfo.isNullOrEmpty() && txtProbeFormat != null) {
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 -> {
}
@ -73,16 +91,28 @@ class ProbeFormatActivity : BaseActivity() {
progressProbe = getView(R.id.progress_probe)
layoutProbe = getView(R.id.layout_probe)
initViewsWithClick(R.id.btn_probe_format)
initViewsWithClick(R.id.btn_retrieve_format)
txtProbeFormat = getView(R.id.txt_probe_format)
}
override fun onViewClick(view: View) {
this.view = view
selectFile()
}
override fun onSelectedFile(filePath: String) {
when (view?.id) {
R.id.btn_probe_format -> {
doHandleProbe(filePath)
}
R.id.btn_retrieve_format -> {
Thread {retrieveMediaMetadata(filePath)}.start()
}
else -> {
}
}
}
/**
* use ffprobe to parse video/audio format metadata
@ -104,4 +134,62 @@ class ProbeFormatActivity : BaseActivity() {
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")
}
}
}

@ -11,10 +11,21 @@
android:id="@+id/btn_probe_format"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:layout_marginTop="50dp"
android:text="@string/media_probe"
android:textColor="@color/colorPrimary"
android:layout_centerHorizontal="true"/>
android:layout_alignParentStart="true"
android:layout_marginStart="20dp"/>
<Button
android:id="@+id/btn_retrieve_format"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="@string/media_retrieve"
android:textColor="@color/colorPrimary"
android:layout_alignParentEnd="true"
android:layout_marginEnd="20dp"/>
<TextView
android:id="@+id/txt_probe_format"
@ -25,6 +36,15 @@
android:textSize="16sp"
android:layout_below="@+id/btn_probe_format"
android:layout_centerHorizontal="true"/>
<ImageView
android:id="@+id/img_frame"
android:layout_width="160dp"
android:layout_height="90dp"
android:layout_below="@+id/txt_probe_format"
android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
<ProgressBar

@ -37,7 +37,8 @@
<string name="media_extra_audio">Audio extract</string>
<string name="media_extract_video">Video extract</string>
<string name="media_play">Media play</string>
<string name="media_probe">Media probe</string>
<string name="media_probe">Probe media info</string>
<string name="media_retrieve">Retrieve media info</string>
<string name="media_dubbing">Media dubbing</string>
<string name="video_cut">Video cut</string>

@ -37,7 +37,8 @@
<string name="media_extra_audio">提取音频</string>
<string name="media_extract_video">提取视频</string>
<string name="media_play">音视频播放</string>
<string name="media_probe">解析多媒体格式</string>
<string name="media_probe">probe多媒体信息</string>
<string name="media_retrieve">retrieve多媒体信息</string>
<string name="media_dubbing">配音</string>
<string name="video_cut">视频剪切</string>

Loading…
Cancel
Save