下面列出了怎么用android.media.MediaFormat的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Selects the video track, if any.
*
* @return the track index, or -1 if no video track is found.
*/
private static int selectTrack(MediaExtractor extractor) {
// Select the first video track we find, ignore the rest.
int numTracks = extractor.getTrackCount();
for (int i = 0; i < numTracks; i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
if (VERBOSE) {
Log.d(TAG, "Extractor selected track " + i + " (" + mime + "): " + format);
}
return i;
}
}
return -1;
}
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodec codec,
Format format,
MediaCrypto crypto,
float codecOperatingRate) {
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
passthroughEnabled = codecInfo.passthrough;
String codecMimeType = passthroughEnabled ? MimeTypes.AUDIO_RAW : codecInfo.codecMimeType;
MediaFormat mediaFormat =
getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
if (passthroughEnabled) {
// Store the input MIME type if we're using the passthrough codec.
passthroughMediaFormat = mediaFormat;
passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
} else {
passthroughMediaFormat = null;
}
}
/**
* Configures encoder and muxer state, and prepares the input Surface.
*/
public VideoEncoderCore(int width, int height, int bitRate, Muxer muxer) throws IOException {
mMuxer = muxer;
mBufferInfo = new MediaCodec.BufferInfo();
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
if (VERBOSE) Log.d(TAG, "format: " + format);
// Create a MediaCodec encoder, and configure it with our format. Get a Surface
// we can use for input and wrap it with a class that handles the EGL work.
mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mInputSurface = mEncoder.createInputSurface();
mEncoder.start();
mTrackIndex = -1;
}
@Override
public MediaFormat getTrackFormat(int index) {
MediaFormat mediaFormat = super.getTrackFormat(index);
if(mMp4Mode) {
/* An MP4 that has been converted from a fragmented to an unfragmented container
* through the isoparser library does only contain the current segment's runtime. To
* return the total runtime, we take the value from the MPD instead.
*/
mediaFormat.setLong(MediaFormat.KEY_DURATION, mMPD.mediaPresentationDurationUs);
}
if(mediaFormat.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
// Return the display aspect ratio as defined in the MPD (can be different from the encoded video size)
mediaFormat.setFloat(MEDIA_FORMAT_EXTENSION_KEY_DAR,
mAdaptationSet.hasPAR() ? mAdaptationSet.par : mRepresentation.calculatePAR());
}
return mediaFormat;
}
/**
* Selects the video track, if any.
*
* @return the track index, or -1 if no video track is found.
*/
private int selectTrack(MediaExtractor extractor) {
// Select the first video track we find, ignore the rest.
int numTracks = extractor.getTrackCount();
for (int i = 0; i < numTracks; i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
if (VERBOSE) {
Log.d(TAG, "Extractor selected track " + i + " (" + mime + "): " + format);
}
return i;
}
}
return -1;
}
/**
* 获得歌曲格式
*/
public static String getType(String mimeType) {
if (mimeType.equals(MediaFormat.MIMETYPE_AUDIO_MPEG)) {
return "mp3";
} else if (mimeType.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
return "flac";
} else if (mimeType.equals(MediaFormat.MIMETYPE_AUDIO_AAC)) {
return "aac";
} else if (mimeType.contains("ape")) {
return "ape";
} else {
try {
if (mimeType.contains("audio/")) {
return mimeType.substring(6, mimeType.length() - 1);
} else {
return mimeType;
}
} catch (Exception e) {
return mimeType;
}
}
}
/**
* Creates an encoder for the given format using the specified codec, taking input from a
* surface.
*
* <p>The surface to use as input is stored in the given reference.
*
* @param codecName of the codec to use
* @param format of the stream to be produced
* @param surfaceReference to store the surface to use as input
*/
private MediaCodec createVideoEncoder(
String codecName,
MediaFormat format,
AtomicReference<Surface> surfaceReference) {
try {
MediaCodec encoder = MediaCodec.createByCodecName(codecName);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
// Must be called before start() is.
surfaceReference.set(encoder.createInputSurface());
encoder.start();
return encoder;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private MediaCodec createMediaCodec(Context context, int bufferSize) throws IOException {
MediaCodec mediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat mediaFormat = new MediaFormat();
mediaFormat.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE);
mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNELS);
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, Prefs.isHardCompressionEnabled(context)? BIT_RATE_WORSE : BIT_RATE_BALANCED);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
try {
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
} catch (Exception e) {
Log.w(TAG, e);
mediaCodec.release();
throw new IOException(e);
}
return mediaCodec;
}
public static TrackResult getFirstVideoAndAudioTrack(MediaExtractor extractor) {
TrackResult trackResult = new TrackResult();
trackResult.mVideoTrackIndex = -1;
trackResult.mAudioTrackIndex = -1;
int trackCount = extractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (trackResult.mVideoTrackIndex < 0 && mime.startsWith("video/")) {
trackResult.mVideoTrackIndex = i;
trackResult.mVideoTrackMime = mime;
trackResult.mVideoTrackFormat = format;
} else if (trackResult.mAudioTrackIndex < 0 && mime.startsWith("audio/")) {
trackResult.mAudioTrackIndex = i;
trackResult.mAudioTrackMime = mime;
trackResult.mAudioTrackFormat = format;
}
if (trackResult.mVideoTrackIndex >= 0 && trackResult.mAudioTrackIndex >= 0) break;
}
if (trackResult.mVideoTrackIndex < 0 || trackResult.mAudioTrackIndex < 0) {
throw new IllegalArgumentException("extractor does not contain video and/or audio tracks.");
}
return trackResult;
}
/**
* 调整aac音量
*
* @param volume [0,100]
* @throws IOException
*/
public static void adjustAacVolume(Context context, VideoProcessor.MediaSource aacSource, String outPath, int volume
, @Nullable VideoProgressListener listener) throws IOException {
String name = "temp_aac_"+System.currentTimeMillis();
File pcmFile = new File(VideoUtil.getVideoCacheDir(context), name + ".pcm");
File pcmFile2 = new File(VideoUtil.getVideoCacheDir(context), name + "_2.pcm");
File wavFile = new File(VideoUtil.getVideoCacheDir(context), name + ".wav");
AudioUtil.decodeToPCM(aacSource, pcmFile.getAbsolutePath(), null, null);
AudioUtil.adjustPcmVolume(pcmFile.getAbsolutePath(), pcmFile2.getAbsolutePath(), volume);
MediaExtractor extractor = new MediaExtractor();
aacSource.setDataSource(extractor);
int trackIndex = VideoUtil.selectTrack(extractor, true);
MediaFormat aacFormat = extractor.getTrackFormat(trackIndex);
int sampleRate = aacFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
int oriChannelCount = aacFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
if (oriChannelCount == 2) {
channelConfig = AudioFormat.CHANNEL_IN_STEREO;
}
new PcmToWavUtil(sampleRate, channelConfig, oriChannelCount, AudioFormat.ENCODING_PCM_16BIT).pcmToWav(pcmFile2.getAbsolutePath(), wavFile.getAbsolutePath());
AudioUtil.encodeWAVToAAC(wavFile.getPath(), outPath, aacFormat, listener);
}
@Test
public void addTrackWhenEncoderMediaFormatReceived() throws Exception {
videoTrackTranscoder.lastExtractFrameResult = TrackTranscoder.RESULT_EOS_REACHED;
videoTrackTranscoder.lastDecodeFrameResult = TrackTranscoder.RESULT_EOS_REACHED;
videoTrackTranscoder.lastEncodeFrameResult = TrackTranscoder.RESULT_FRAME_PROCESSED;
MediaFormat encoderMediaFormat = new MediaFormat();
doReturn(MediaCodec.INFO_OUTPUT_FORMAT_CHANGED).when(encoder).dequeueOutputFrame(anyLong());
doReturn(encoderMediaFormat).when(encoder).getOutputFormat();
doReturn(VIDEO_TRACK).when(mediaTarget).addTrack(any(MediaFormat.class), anyInt());
int result = videoTrackTranscoder.processNextFrame();
ArgumentCaptor<MediaFormat> mediaFormatArgumentCaptor = ArgumentCaptor.forClass(MediaFormat.class);
verify(mediaTarget).addTrack(mediaFormatArgumentCaptor.capture(), eq(VIDEO_TRACK));
assertThat(mediaFormatArgumentCaptor.getValue(), is(encoderMediaFormat));
assertThat(videoTrackTranscoder.targetTrack, is(VIDEO_TRACK));
assertThat(result, is(TrackTranscoder.RESULT_OUTPUT_MEDIA_FORMAT_CHANGED));
}
public static TrackResult getFirstVideoAndAudioTrack(MediaExtractor extractor) {
TrackResult trackResult = new TrackResult();
trackResult.mVideoTrackIndex = -1;
trackResult.mAudioTrackIndex = -1;
int trackCount = extractor.getTrackCount();
for (int i = 0; i < trackCount; i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (trackResult.mVideoTrackIndex < 0 && mime.startsWith("video/")) {
trackResult.mVideoTrackIndex = i;
trackResult.mVideoTrackMime = mime;
trackResult.mVideoTrackFormat = format;
} else if (trackResult.mAudioTrackIndex < 0 && mime.startsWith("audio/")) {
trackResult.mAudioTrackIndex = i;
trackResult.mAudioTrackMime = mime;
trackResult.mAudioTrackFormat = format;
}
if (trackResult.mVideoTrackIndex >= 0 && trackResult.mAudioTrackIndex >= 0) break;
}
if (trackResult.mVideoTrackIndex < 0 || trackResult.mAudioTrackIndex < 0) {
throw new IllegalArgumentException("extractor does not contain video and/or audio tracks.");
}
return trackResult;
}
private MediaCodec createMediaCodec(int bufferSize) throws IOException {
MediaCodec mediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat mediaFormat = new MediaFormat();
mediaFormat.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE);
mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNELS);
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
try {
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
} catch (Exception e) {
Log.w(TAG, e);
mediaCodec.release();
throw new IOException(e);
}
return mediaCodec;
}
private void init() {
mBufferInfo = new MediaCodec.BufferInfo();
try {
mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
MediaFormat mediaFormat = MediaFormat.createAudioFormat(MIME_TYPE,
sampleRate, channelCount);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
KEY_AAC_PROFILE);
mEncoder.configure(mediaFormat, null, null,
MediaCodec.CONFIGURE_FLAG_ENCODE);
mEncoder.start();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 初始化编码器
*/
private void initMediaEncode() {
getEncodeColor();
try {
MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, mDstWidth, mDstHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, 1024 * 512);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 27);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mVideoEncodeColor);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
mMediaEncode = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
mMediaEncode.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
} catch (IOException e) {
e.printStackTrace();
}
if (mMediaEncode == null) {
Log.e(TAG, "create mMediaEncode failed");
return;
}
mMediaEncode.start();
}
/**
* Returns the framework {@link MediaFormat} that can be used to configure a {@link MediaCodec}
* for decoding the given {@link Format} for playback.
*
* @param format The format of the media.
* @param codecMimeType The MIME type handled by the codec.
* @param codecMaxInputSize The maximum input size supported by the codec.
* @param codecOperatingRate The codec operating rate, or {@link #CODEC_OPERATING_RATE_UNSET} if
* no codec operating rate should be set.
* @return The framework media format.
*/
@SuppressLint("InlinedApi")
protected MediaFormat getMediaFormat(
Format format, String codecMimeType, int codecMaxInputSize, float codecOperatingRate) {
MediaFormat mediaFormat = new MediaFormat();
// Set format parameters that should always be set.
mediaFormat.setString(MediaFormat.KEY_MIME, codecMimeType);
mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, format.channelCount);
mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, format.sampleRate);
MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
// Set codec max values.
MediaFormatUtil.maybeSetInteger(mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, codecMaxInputSize);
// Set codec configuration values.
if (Util.SDK_INT >= 23) {
mediaFormat.setInteger(MediaFormat.KEY_PRIORITY, 0 /* realtime priority */);
if (codecOperatingRate != CODEC_OPERATING_RATE_UNSET) {
mediaFormat.setFloat(MediaFormat.KEY_OPERATING_RATE, codecOperatingRate);
}
}
return mediaFormat;
}
/**
*
* @param media
* @param vlcTracks
* @param lib
* @return
*/
static com.google.android.exoplayer.TrackInfo[] vlc2exoTracks(long duration,
org.videolan.libvlc.Media.Track[] vlcTracks, LibVLC lib) {
com.google.android.exoplayer.TrackInfo[] res = new com.google.android.exoplayer.TrackInfo[vlcTracks.length];
System.out.println("ExoVlcUtil.vlc2exoTracks() vlcTracks = " + vlcTracks.length);
// Media.Track
for (int i = 0; i < res.length; i++) {
MediaFormat mf = track2mediaFormat(vlcTracks[i]);
res[i] = new TrackInfo(mf.getString(MediaFormat.KEY_MIME), duration);
System.out.println("\t track " + i + " mime type =" + mf.getString(MediaFormat.KEY_MIME) + " duration ="
+ duration);
}
/*
* System.out.println(">>>> ExoVlcUtil.vlc2exoTracks() vlcTracks.length = "
* +vlcTracks.length); long l; for (int i = 0; i < vlcTracks.length;
* i++) { org.videolan.libvlc.TrackInfo vt = vlcTracks[i];
* System.out.println("\t\t >>>>>Codec("+i+") "+vlcTracks[i].Codec);
* res[i] = new TrackInfo( vt.Codec, (l=lib.getLength()) == -1 ?
* com.google.android.exoplayer.C.UNKNOWN_TIME_US : l * MS_2_MICRO); }
*/
return res;
}
public int tryConfig(Surface surface, byte[] sps, byte[] pps)
{
int[] width = new int[1];
int[] height = new int[1];
AvcUtils.parseSPS(sps, width, height);
mMF = MediaFormat.createVideoFormat(MIME_TYPE, width[0], height[0]);
mMF.setByteBuffer("csd-0", ByteBuffer.wrap(sps));
mMF.setByteBuffer("csd-1", ByteBuffer.wrap(pps));
mMF.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, width[0] * height[0]);
mMC.configure(mMF, surface, null, 0);
Log.i("AvcDecoder", "Init, configure");
mStatus = STATUS_IDLE;
return 0;
}
public Format3GP(EncoderInfo info, File out) {
MediaFormat format = new MediaFormat();
// for high bitrate AMR_WB
{
// final int kBitRates[] = {6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850};
// format.setString(MediaFormat.KEY_MIME, "audio/amr-wb");
// format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate);
// format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels);
// format.setInteger(MediaFormat.KEY_BIT_RATE, 23850); // set maximum
}
// for low bitrate, AMR_NB
{
// final int kBitRates[] = {4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200};
format.setString(MediaFormat.KEY_MIME, "audio/3gpp");
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, info.sampleRate); // 8000 only supported
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, info.channels);
format.setInteger(MediaFormat.KEY_BIT_RATE, 12200); // set maximum
}
create(info, format, out);
}
public int getDuration() {
if(mCurrentState.ordinal() <= State.PREPARING.ordinal() && mCurrentState.ordinal() >= State.RELEASING.ordinal()) {
mCurrentState = State.ERROR;
throw new IllegalStateException();
}
return mVideoFormat != null ? (int)(mVideoFormat.getLong(MediaFormat.KEY_DURATION)/1000) :
mAudioFormat != null && mAudioFormat.containsKey(MediaFormat.KEY_DURATION) ? (int)(mAudioFormat.getLong(MediaFormat.KEY_DURATION)/1000) : 0;
}
/**
* Instantiates and starts the encoder.
* @throws IOException The encoder cannot be configured
*/
private void configureEncoder() throws IOException {
mEncoder = MediaCodec.createByCodecName(mEncoderName);
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BITRATE);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAMERATE);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mEncoderColorFormat);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
mEncoder.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mEncoder.start();
}
@Override
public MediaFormat createVideoOutputFormat(MediaFormat inputFormat) {
// TODO: detect non-baseline profile and throw exception
int width = inputFormat.getInteger(MediaFormat.KEY_WIDTH);
int height = inputFormat.getInteger(MediaFormat.KEY_HEIGHT);
MediaFormat outputFormat = MediaFormatPresets.getExportPreset960x540(width, height);
int outWidth = outputFormat.getInteger(MediaFormat.KEY_WIDTH);
int outHeight = outputFormat.getInteger(MediaFormat.KEY_HEIGHT);
Log.d(TAG, String.format("inputFormat: %dx%d => outputFormat: %dx%d", width, height, outWidth, outHeight));
return outputFormat;
}
@CalledByNative
private boolean configureVideo(MediaFormat format, Surface surface, MediaCrypto crypto,
int flags) {
try {
mMediaCodec.configure(format, surface, crypto, flags);
return true;
} catch (IllegalStateException e) {
Log.e(TAG, "Cannot configure the video codec " + e.toString());
}
return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.mCameraCapture).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
startActivity(new Intent(MainActivity.this, CameraCaptureActivity.class));
}
});
TextView tvInfo = (TextView) findViewById(R.id.mTvInfo);
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, 1080, 720);
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, 100000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(MIME_TYPE);
tvInfo.setText(
"MaxSupportedInstances: " + capabilities.getMaxSupportedInstances() + "\n"
);
}
@Override
protected void onOutputFormatChanged(MediaCodec codec, MediaFormat outputFormat)
throws ExoPlaybackException {
@C.Encoding int encoding;
MediaFormat format;
if (passthroughMediaFormat != null) {
encoding = MimeTypes.getEncoding(passthroughMediaFormat.getString(MediaFormat.KEY_MIME));
format = passthroughMediaFormat;
} else {
encoding = pcmEncoding;
format = outputFormat;
}
int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
int[] channelMap;
if (codecNeedsDiscardChannelsWorkaround && channelCount == 6 && this.channelCount < 6) {
channelMap = new int[this.channelCount];
for (int i = 0; i < this.channelCount; i++) {
channelMap[i] = i;
}
} else {
channelMap = null;
}
try {
audioSink.configure(encoding, channelCount, sampleRate, 0, channelMap, encoderDelay,
encoderPadding);
} catch (AudioSink.ConfigurationException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
}
}
/**
* 创建音频MediaFormat[aac]
*
* @param sampleRate 采样率
* @param channelMask 声道
* @param channelCount 声道数
* @return
*/
public static MediaFormat createAudioFormat(int sampleRate, int channelMask, int channelCount) {
MediaFormat format = MediaFormat.createAudioFormat(MIME_TYPE_AAC, sampleRate, channelCount);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
// 声道
format.setInteger(MediaFormat.KEY_CHANNEL_MASK, channelMask);
// 声道数
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channelCount);
// 音频bit率
format.setInteger(MediaFormat.KEY_BIT_RATE, AUDIO_BIT_RATE);
// 统一设置最大缓冲容量,否则在音频转码时因为大小不一致会报错
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, BUFFER_SIZE);
return format;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
public IMediaFormat getFormat() {
if (mTrackInfo == null)
return null;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return null;
MediaFormat mediaFormat = mTrackInfo.getFormat();
if (mediaFormat == null)
return null;
return new AndroidMediaFormat(mediaFormat);
}
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodec codec,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate) {
String codecMimeType = codecInfo.codecMimeType;
codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
MediaFormat mediaFormat =
getMediaFormat(
format,
codecMimeType,
codecMaxValues,
codecOperatingRate,
deviceNeedsNoPostProcessWorkaround,
tunnelingAudioSessionId);
if (surface == null) {
Assertions.checkState(shouldUseDummySurface(codecInfo));
if (dummySurface == null) {
dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
}
surface = dummySurface;
}
codec.configure(mediaFormat, surface, crypto, 0);
if (Util.SDK_INT >= 23 && tunneling) {
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
}
}
public MediaFormat createAudioMediaFormat() {
MediaFormat format = MediaFormat.createAudioFormat(audioMIME, samplingRate, 2);
format.setInteger(MediaFormat.KEY_BIT_RATE, audioBitRate);
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, audioBufferSize);
return format;
}
public boolean setEncoder(int sampleRate, int channels, int bitRate) throws Exception
{
encoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channels);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, sampleRate);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate * 1024);//AAC-HE 64kbps
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
initAudioRecord(sampleRate);
return true;
}