2024年C C++最全安卓-录屏录音录像_android mediacodec 录视频,2024年最新字节跳动C C++金三银四解析

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

    super.onActivityResult(requestCode, resultCode, data);
}

### 2、录音


相关技术就是:MediaCodec硬编码和MediaMuxer生成mp3文件



package com.example.myapplication;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.media.MediaRecorder;
import android.os.Build;
import android.util.Log;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class AudioEncoder implements Runnable {

private String mime = "audio/mp4a-latm";
private AudioRecord mRecorder;
private MediaCodec mEnc;
private int rate=256000;

//录音设置
private int sampleRate=44100;   //采样率,默认44.1k
private int channelCount=2;     //音频采样通道,默认2通道
private int channelConfig= AudioFormat.CHANNEL_IN_STEREO;        //通道设置,默认立体声
private int audioFormat=AudioFormat.ENCODING_PCM_16BIT;     //设置采样数据格式,默认16比特PCM
private FileOutputStream fos;

private byte[] buffer;
private boolean isRecording;
private Thread mThread;
private int bufferSize;

private String mSavePath;

private MediaMuxer mMuxer;  //多路复用器,用于音视频混合
private int mAudioTrack=-1;

public AudioEncoder(){

}
public void setMuxer(MediaMuxer mMuxer){this.mMuxer=mMuxer;}
public void setMime(String mime){
    this.mime=mime;
}

public void setRate(int rate){
    this.rate=rate;
}

public void setSampleRate(int sampleRate){
    this.sampleRate=sampleRate;
}

public void setSavePath(String path){
    this.mSavePath=path;
}

public boolean prepare() throws IOException {
    //fos=new FileOutputStream(mSavePath);
    //音频编码相关
    MediaFormat format= MediaFormat.createAudioFormat(mime,sampleRate,channelCount);
    format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);

// format.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_IN_MONO);
format.setInteger(MediaFormat.KEY_BIT_RATE, rate);
mEnc=MediaCodec.createEncoderByType(mime);
mEnc.configure(format,null,null,MediaCodec.CONFIGURE_FLAG_ENCODE);
//音频录制相关`
bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat)*2;
buffer=new byte[bufferSize];
mRecorder=new AudioRecord(MediaRecorder.AudioSource.MIC,sampleRate,channelConfig,audioFormat,bufferSize);
if (mRecorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
return false;
}

    mMuxer=new MediaMuxer(mSavePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
    return true;
}

public void start() throws InterruptedException {
    mEnc.start();
    //开始录制音频
    try{
        // 防止某些手机崩溃,例如联想
        mRecorder.startRecording();
    }catch (IllegalStateException e){
        e.printStackTrace();
    }
    if(mThread!=null&&mThread.isAlive()){
        isRecording=false;
        mThread.join();
    }
    isRecording=true;
    mThread=new Thread(this);
    mThread.start();
}

private ByteBuffer getInputBuffer(int index){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        return mEnc.getInputBuffer(index);
    }else{
        return mEnc.getInputBuffers()[index];
    }
}

private ByteBuffer getOutputBuffer(int index){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        return mEnc.getOutputBuffer(index);
    }else{
        return mEnc.getOutputBuffers()[index];
    }
}

//TODO Add End Flag
private void readOutputData() throws IOException{
    int index=mEnc.dequeueInputBuffer(-1);
    if(index>=0){
        final ByteBuffer buffer=getInputBuffer(index);
        buffer.clear();
        int length=mRecorder.read(buffer,bufferSize);
        if(length>0){
            mEnc.queueInputBuffer(index,0,length,System.nanoTime()/1000,0);
        }else{
            Log.e("wuwang","length-->"+length);
        }
    }
    MediaCodec.BufferInfo mInfo=new MediaCodec.BufferInfo();
    int outIndex;
    do{
        outIndex=mEnc.dequeueOutputBuffer(mInfo,0);
        Log.e("wuwang","audio flag---->"+mInfo.flags+"/"+outIndex);
        if(outIndex>=0){
            ByteBuffer buffer=getOutputBuffer(outIndex);
            buffer.position(mInfo.offset);

// byte[] temp=new byte[mInfo.size+7];
// buffer.get(temp,7,mInfo.size);
// addADTStoPacket(temp,temp.length);
if(mAudioTrack>=0&&mInfo.size>0&&mInfo.presentationTimeUs>0){
try {
mMuxer.writeSampleData(mAudioTrack,buffer,mInfo);
}catch (Exception e){
//Log.e(TAG,“audio error:size=”+mInfo.size+“/offset=”
// +mInfo.offset+“/timeUs=”+mInfo.presentationTimeUs);
e.printStackTrace();
}
}
mEnc.releaseOutputBuffer(outIndex,false);
if((mInfo.flags&MediaCodec.BUFFER_FLAG_END_OF_STREAM)!=0){
//Log.e(TAG,“audio end”);
return ;
}
}else if(outIndex ==MediaCodec.INFO_TRY_AGAIN_LATER){

        }else if(outIndex==MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){
            mAudioTrack=mMuxer.addTrack(mEnc.getOutputFormat());
            //Log.e(TAG,"add audio track-->"+mAudioTrack);
            if(mAudioTrack>=0){
                mMuxer.start();
            }
        }
    }while (outIndex>=0);
}

/**
 * 给编码出的aac裸流添加adts头字段
 * @param packet 要空出前7个字节,否则会搞乱数据
 * @param packetLen
 */
private void addADTStoPacket(byte[] packet, int packetLen) {
    int profile = 2;  //AAC LC
    int freqIdx = 4;  //44.1KHz
    int chanCfg = 2;  //CPE
    packet[0] = (byte)0xFF;
    packet[1] = (byte)0xF9;
    packet[2] = (byte)(((profile-1)<<6) + (freqIdx<<2) +(chanCfg>>2));
    packet[3] = (byte)(((chanCfg&3)<<6) + (packetLen>>11));
    packet[4] = (byte)((packetLen&0x7FF) >> 3);
    packet[5] = (byte)(((packetLen&7)<<5) + 0x1F);
    packet[6] = (byte)0xFC;
}

/**
 * 停止录制
 */
public void stop(){
    try {
        isRecording=false;
        mThread.join();
        mRecorder.stop();
        mEnc.stop();
        mEnc.release();

// fos.flush();
// fos.close();
mAudioTrack=-1;
mMuxer.stop();
mMuxer.release();
} catch (Exception e){
e.printStackTrace();
}
}

@Override
public void run() {
    while (isRecording){
        try {
            readOutputData();

// fos.write(buffer,0,length);
} catch (IOException e) {
e.printStackTrace();
}
}
}

}


### 3、录像


涉及技术点:Camera摄像机类、MediaCodec硬编码,需要注意的是一些格式的转换,最好是使用C++jni调用,单纯用java有点花屏  
 注意:需要surfaceView控件,如果不需要显示则可以设置为单位1  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/88f3f99a6eef49e092084511938d45fc.jpg?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAencxOTk2,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)


![img](https://img-blog.csdnimg.cn/img_convert/cec3160a186efd0eb22c40feff16e4a4.png)
![img](https://img-blog.csdnimg.cn/img_convert/174e62535fa98f75392f7786bc28fcc5.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

)]
[外链图片转存中...(img-pPzRS92g-1715538863296)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618668825)**

  • 29
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值