Dana
8 天以前 01d5238738887b1739cede0c6b589b8c4e34031d
app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraRecordManager.java
@@ -366,6 +366,20 @@
                    Timber.d("音频录制已启动");
                }
                
                // 主动检查音频编码器输出格式(可能在处理数据前就有格式)
                try {
                    MediaFormat audioFormat = audioEncoder.getOutputFormat();
                    if (audioFormat != null) {
                        synchronized (UsbCameraRecordManager.this) {
                            audioTrackIndex = mediaMuxer.addTrack(audioFormat);
                            Timber.d("音频轨道已添加(主动检查): %d", audioTrackIndex);
                            checkAndStartMuxer();
                        }
                    }
                } catch (Exception e) {
                    Timber.d("音频编码器输出格式尚未准备好,将在处理数据时添加");
                }
                // 启动音频编码线程
                audioThread = new AudioThread();
                audioThread.start();
@@ -374,6 +388,8 @@
                
                long frameCount = 0;
                long lastFileChangeTime = System.currentTimeMillis();
                long audioTrackWaitStartTime = System.currentTimeMillis();
                final long AUDIO_TRACK_TIMEOUT_MS = 3000; // 3秒超时
                
                // 循环处理摄像头数据
                while (isRunning && cameraExists) {
@@ -432,6 +448,27 @@
                    if (videoEncoder != null && mediaMuxer != null) {
                        encodeFrame(buffer, frameCount, width, height);
                        frameCount++;
                        // 如果音频轨道超时未准备好,尝试仅用视频轨道启动
                        if (!muxerStarted && videoTrackIndex >= 0 && audioTrackIndex < 0) {
                            // 重用循环中已定义的 currentTime 变量
                            if (currentTime - audioTrackWaitStartTime > AUDIO_TRACK_TIMEOUT_MS) {
                                Timber.w("音频轨道超时未准备好,仅使用视频轨道启动Muxer");
                                synchronized (UsbCameraRecordManager.this) {
                                    // 创建一个假的音频轨道索引,或者直接启动(但MediaMuxer要求至少一个轨道)
                                    // 实际上MediaMuxer需要至少一个轨道,所以如果视频轨道准备好了就可以启动
                                    if (videoTrackIndex >= 0) {
                                        try {
                                            mediaMuxer.start();
                                            muxerStarted = true;
                                            Timber.d("Muxer started with video track only: %d", videoTrackIndex);
                                        } catch (Exception e) {
                                            Timber.e(e, "Failed to start muxer with video only");
                                        }
                                    }
                                }
                            }
                        }
                    }
                    
                    // 控制帧率,约20fps
@@ -482,12 +519,17 @@
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outputBufferIndex = videoEncoder.dequeueOutputBuffer(bufferInfo, 0);
                
                while (outputBufferIndex >= 0) {
                while (outputBufferIndex != MediaCodec.INFO_TRY_AGAIN_LATER) {
                    if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                        // 输出格式改变,添加视频轨道
                        MediaFormat newFormat = videoEncoder.getOutputFormat();
                        videoTrackIndex = mediaMuxer.addTrack(newFormat);
                        checkAndStartMuxer();
                        synchronized (UsbCameraRecordManager.this) {
                            videoTrackIndex = mediaMuxer.addTrack(newFormat);
                            Timber.d("视频轨道已添加: %d", videoTrackIndex);
                            checkAndStartMuxer();
                        }
                        outputBufferIndex = videoEncoder.dequeueOutputBuffer(bufferInfo, 0);
                        continue;
                    } else if (outputBufferIndex >= 0) {
                        ByteBuffer outputBuffer = videoEncoder.getOutputBuffer(outputBufferIndex);
                        if (outputBuffer != null && muxerStarted && videoTrackIndex >= 0) {
@@ -512,9 +554,15 @@
     */
    private synchronized void checkAndStartMuxer() {
        if (!muxerStarted && videoTrackIndex >= 0 && audioTrackIndex >= 0) {
            mediaMuxer.start();
            muxerStarted = true;
            try {
                mediaMuxer.start();
                muxerStarted = true;
                Timber.d("Muxer started, video track: %d, audio track: %d", videoTrackIndex, audioTrackIndex);
            } catch (Exception e) {
                Timber.e(e, "Failed to start muxer");
            }
        } else {
            Timber.d("Muxer not started yet, video track: %d, audio track: %d", videoTrackIndex, audioTrackIndex);
        }
    }
    
@@ -580,12 +628,17 @@
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outputBufferIndex = audioEncoder.dequeueOutputBuffer(bufferInfo, 0);
                
                while (outputBufferIndex >= 0) {
                while (outputBufferIndex != MediaCodec.INFO_TRY_AGAIN_LATER) {
                    if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                        // 输出格式改变,添加音频轨道
                        MediaFormat newFormat = audioEncoder.getOutputFormat();
                        audioTrackIndex = mediaMuxer.addTrack(newFormat);
                        checkAndStartMuxer();
                        synchronized (UsbCameraRecordManager.this) {
                            audioTrackIndex = mediaMuxer.addTrack(newFormat);
                            Timber.d("音频轨道已添加: %d", audioTrackIndex);
                            checkAndStartMuxer();
                        }
                        outputBufferIndex = audioEncoder.dequeueOutputBuffer(bufferInfo, 0);
                        continue;
                    } else if (outputBufferIndex >= 0) {
                        ByteBuffer outputBuffer = audioEncoder.getOutputBuffer(outputBufferIndex);
                        if (outputBuffer != null && muxerStarted && audioTrackIndex >= 0) {