尤教授 2018-11-05 08:50 采纳率: 42.9%
浏览 1667
已采纳

手动创建MediaFormat时,是否需要通过muxer的writeSampleData方法写入PPS和SPS?

如题,我是参考 http://blog.51cto.com/ticktick/1710743 改写了一下,但是MediaFormat是通过手动创建的,通过Extractor解出来的Buffer手动的创建MediaFormat,遇到几个问题:将第一帧写入MediaFormat后手动调用MediaExtractor的advance方法运行后直接crash,error是muxer fail to stop 2.SPS和PPS写入MediaFormat后是否还需要再通过muxer写入,不写入的话时间戳会不会有问题?

  • 写回答

2条回答 默认 最新

  • 尤教授 2018-11-06 02:25
    关注

    public class MainActivity extends Activity {

    private static final String SDCARD_PATH = Environment.getExternalStorageDirectory().getPath();
    private static final String INPUT_FILEPATH = SDCARD_PATH + "/input.mp4";
    private static final String OUTPUT_FILEPATH = SDCARD_PATH + "/output.mp4";
    private int i = 0;
    private TextView mLogView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLogView = (TextView) findViewById(R.id.LogView);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    transcode(INPUT_FILEPATH, OUTPUT_FILEPATH);
                } catch (IOException e) {
                    e.printStackTrace();
                    logout(e.getMessage());
                }
            }
        }).start();
    }
    
    protected boolean transcode(String input, String output) throws IOException {
    
        logout("start processing...");
    
        MediaMuxer muxer = null;
    
        MediaExtractor extractor = new MediaExtractor();
        extractor.setDataSource(input);
    
        logout("start demuxer: " + input);
    
        MediaFormat videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720);
    
        extractor.selectTrack(0);
    

    // if (muxer == null) {
    // logout("no video found !");
    // return false;
    // }

        BufferInfo info = new BufferInfo();
        info.presentationTimeUs = 0;
        ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024 * 2);
    
        int i = - 1;
        while (true) {
            i++;
            int sampleSize = extractor.readSampleData(buffer, 0);
            if (sampleSize < 0) {
                logout("read sample data failed , break !");
                break;
            }
            if (i == 0 ){
                byte[] sps_header = new byte[sampleSize];
                for (int j = 0;j < sampleSize;j++){
                    sps_header[j] = buffer.array()[sampleSize];
                }
    
                //SPS
                videoFormat.setByteBuffer("csd-0", ByteBuffer.wrap(sps_header));
                extractor.advance();
                continue;
            }else if (i == 1){
                //PPS
                byte[] pps_header = new byte[sampleSize];
                for (int j = 0; j < sampleSize; j++){
                    pps_header[j] = buffer.array()[sampleSize];
                }
                videoFormat.setByteBuffer("csd-1",ByteBuffer.wrap(pps_header));
                videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
                videoFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080);
                videoFormat.setInteger(MediaFormat.KEY_CAPTURE_RATE, 25);
    
                muxer = new MediaMuxer(output,OutputFormat.MUXER_OUTPUT_MPEG_4);
                muxer.addTrack(videoFormat);
                muxer.start();
                continue;
            }
    
            Log.d("xiaxingyu","i = " + i);
            info.offset = 0;
            info.size = sampleSize;
            info.flags = extractor.getSampleFlags();
            info.presentationTimeUs = extractor.getSampleTime();
            boolean keyframe = (info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) > 0;
            logout("write sample " + keyframe + ", " + sampleSize + ", " + info.presentationTimeUs);
            muxer.writeSampleData(0, buffer, info);
            extractor.advance();
        }
    
        extractor.release();
    
        muxer.stop();
        muxer.release();
    
        logout("process success !");
    
        return true;
    }
    
    private void logout(final String content) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.i("MediaDemo", content);
                mLogView.setText(mLogView.getText() + "\n" + content);
            }
        });
    }
    

    }

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 电脑开机过商标后就直接这样,求解各位
  • ¥15 mysql , 用自己创建的本地主机和用户名 登录不上
  • ¥15 关于#web项目#的问题,请各位专家解答!
  • ¥15 vmtools环境不正常
  • ¥15 请问如何在Ubuntu系统中安装使用microsoft R open?
  • ¥15 jupyter notebook
  • ¥30 informer时间序列预测
  • ¥20 SSR引物多态性分析
  • ¥15 大漠插件在Win11易语言注册调用和免注册灵异事件,VS上注册调用完全没问题
  • ¥15 Addressable缓存机制做热更新的问题