the next line causes an error invalid trackIndex but it is 0:
mediaMuxer.writeSampleData(trackIndex, compressedBuffer, bufferInfo)
Here is my full fun:
private fun reduceVideoSize(inputDescriptor: FileDescriptor, outputDescriptor: FileDescriptor, compressionPercentage: Int) {
lifecycleScope.launch {
Log.d("reduceVideoSize", "STARTED")
val mediaExtractor = MediaExtractor()
mediaExtractor.setDataSource(inputDescriptor)
val trackIndex = selectTrack(mediaExtractor, false)
Log.d("TRACK INDEX", trackIndex.toString())
mediaExtractor.selectTrack(trackIndex)
//val mediaFormat = mediaExtractor.getTrackFormat(trackIndex)
val mediaFormat = MediaFormat.createVideoFormat("video/avc", 1920, 1080)
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 2000000)
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30)
mediaFormat.setInteger(
MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible
)
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1)
Log.d("MediaFormat", mediaFormat.toString())
val mimeType = mediaFormat.getString(MediaFormat.KEY_MIME)
Log.d("MIME TYPE", mimeType.toString())
val mediaCodec = MediaCodec.createEncoderByType(mimeType!!)
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
//val inputSurface = mediaCodec.createInputSurface()
mediaCodec.start()
val mediaMuxer = MediaMuxer(outputDescriptor, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
val bufferInfo = MediaCodec.BufferInfo()
var isEOS = false
val timeoutUs = 10000L
while (!isEOS) {
val inputBufferIndex = mediaCodec.dequeueInputBuffer(timeoutUs)
if (inputBufferIndex >= 0) {
val inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex)
val sampleSize = mediaExtractor.readSampleData(inputBuffer!!, 0)
if (sampleSize < 0) {
mediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)
isEOS = true
} else {
mediaCodec.queueInputBuffer(inputBufferIndex, 0, sampleSize, mediaExtractor.sampleTime, 0)
mediaExtractor.advance()
}
}
val outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, timeoutUs)
if (outputBufferIndex >= 0) {
val outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex)
outputBuffer?.let {
val bufferData = ByteArray(bufferInfo.size)
it.get(bufferData)
val compressedSize = bufferData.size * compressionPercentage / 100
val compressedBuffer = ByteBuffer.allocate(compressedSize)
compressedBuffer.put(bufferData, 0, compressedSize)
Log.d("TRACK INDEX", trackIndex.toString())
//next row makes an error trackIndex is invalid (0)
mediaMuxer.writeSampleData(trackIndex, compressedBuffer, bufferInfo)
}
mediaCodec.releaseOutputBuffer(outputBufferIndex, false)
}
if (bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM != 0) {
isEOS = true
}
}
mediaMuxer.stop()
mediaMuxer.release()
mediaExtractor.release()
mediaCodec.stop()
mediaCodec.release()
}
}
private fun selectTrack(extractor: MediaExtractor, audio: Boolean): Int {
val numTracks = extractor.trackCount
Log.d("NUMTRACKS", numTracks.toString())
for (i in 0 until numTracks) {
val format = extractor.getTrackFormat(i)
val mime = format.getString(MediaFormat.KEY_MIME)
if (audio) {
if (mime.let{it!!.startsWith("audio/")}) {
Log.d("TRACK $i", "got audiotrack")
return i
}
} else {
if (mime.let{it!!.startsWith("video/")}) {
Log.d("TRACK $i", "got videotrack")
return i
}
}
}
return -1
}
Looks like the media muxer is not setup properly with the added tracks. Here is more information: https://developer.android.com/reference/android/media/MediaMuxer
This code is from the documentation just in case.
MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
// SetUp Video/Audio Tracks.
MediaFormat audioFormat = new MediaFormat(...);
MediaFormat videoFormat = new MediaFormat(...);
int audioTrackIndex = muxer.addTrack(audioFormat);
int videoTrackIndex = muxer.addTrack(videoFormat);
// Setup Metadata Track
MediaFormat metadataFormat = new MediaFormat(...);
metadataFormat.setString(KEY_MIME, "application/gyro");
int metadataTrackIndex = muxer.addTrack(metadataFormat);
muxer.start();
while(..) {
// Allocate bytebuffer and write gyro data(x,y,z) into it.
ByteBuffer metaData = ByteBuffer.allocate(bufferSize);
metaData.putFloat(x);
metaData.putFloat(y);
metaData.putFloat(z);
BufferInfo metaInfo = new BufferInfo();
// Associate this metadata with the video frame by setting
// the same timestamp as the video frame.
metaInfo.presentationTimeUs = currentVideoTrackTimeUs;
metaInfo.offset = 0;
metaInfo.flags = 0;
metaInfo.size = bufferSize;
muxer.writeSampleData(metadataTrackIndex, metaData, metaInfo);
};
muxer.stop();
muxer.release();
}
Check the Setup Video/Audio Tracks.
section so that you can add those and use them later in your code.