Воспроизведение декодированного звука javacv-ffmpeg на Android с помощью Audiotrack

Я разрабатываю приложение для Android, в котором мне нужно воспроизводить аудиопоток AAC в прямом эфире, поступающий с сервера Red5.
Я успешно декодировал аудиопоток с помощью javacv-ffmpeg.
Но моя проблема заключается в том, как воспроизводить аудио из декодированного образцы.
Я пробовал следующим образом

int len = avcodec.avcodec_decode_audio4( audio_c,  samples_frame,  got_frame,  pkt2);
if (len <= 0){
    this.pkt2.size(0);
} else {
    if (this.got_frame[0] != 0) {
            long pts = avutil.av_frame_get_best_effort_timestamp(samples_frame);
            int sample_format = samples_frame.format();
                   int planes = avutil.av_sample_fmt_is_planar(sample_format) != 0 ? samples_frame.channels() : 1;
                   int data_size = avutil.av_samples_get_buffer_size((IntPointer)null, audio_c.channels(), samples_frame.nb_samples(), audio_c.sample_fmt(), 1) / planes;

                   if ((samples_buf == null) || (samples_buf.length != planes)) {

                       samples_ptr = new BytePointer[planes];
                       samples_buf = new Buffer[planes];
                   }
                           BytePointer ptemp = samples_frame.data(0);
               BytePointer[] temp_ptr = new BytePointer[1];
               temp_ptr[0] = ptemp.capacity(sample_size);
               ByteBuffer btemp = ptemp.asBuffer();
               byte[] buftemp = new byte[sample_size];
               btemp.get(buftemp, 0, buftemp.length);

                           play the buftemp[] with audiotrack.....
        }

Но из динамиков слышен только шум, требуется ли какая-либо обработка AVFrame, которую мы получаем от decode_audio4(...) .
Входящий аудиопоток правильно закодирован кодеком AAC.
Любая помощь, предложения приветствуются.
Заранее спасибо.


person Ichigo Kurosaki    schedule 31.03.2014    source источник
comment
Я тоже столкнулся с той же проблемой. :(   -  person ShihabSoft    schedule 09.03.2015
comment
@ Ичиго Куросаки, ты нашел какое-нибудь решение ??? пожалуйста, поделитесь им здесь, если вы нашли   -  person Nikul Rao    schedule 04.11.2016


Ответы (2)


Вы можете использовать класс FFmpegFrameGrabber для захвата потока. И извлеките звук с помощью класса FloatBuffer. Это пример Java

public class PlayVideoAndAudio extends Application
{
    private static final Logger LOG = Logger.getLogger(JavaFxPlayVideoAndAudio.class.getName());
    private static final double SC16 = (double) 0x7FFF + 0.4999999999999999;

    private static volatile Thread playThread;

    public static void main(String[] args)
    {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        String source = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov";

        StackPane root = new StackPane();
        ImageView imageView = new ImageView();

        root.getChildren().add(imageView);
        imageView.fitWidthProperty().bind(primaryStage.widthProperty());
        imageView.fitHeightProperty().bind(primaryStage.heightProperty());

        Scene scene = new Scene(root, 640, 480);

        primaryStage.setTitle("Video + audio");
        primaryStage.setScene(scene);
        primaryStage.show();

        playThread = new Thread(() -> {
            try {
                FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(source);
                grabber.start();
                primaryStage.setWidth(grabber.getImageWidth());
                primaryStage.setHeight(grabber.getImageHeight());
                AudioFormat audioFormat = new AudioFormat(grabber.getSampleRate(), 16, grabber.getAudioChannels(), true, true);

                DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
                SourceDataLine soundLine = (SourceDataLine) AudioSystem.getLine(info);
                soundLine.open(audioFormat);
                soundLine.start();

                Java2DFrameConverter converter = new Java2DFrameConverter();

                ExecutorService executor = Executors.newSingleThreadExecutor();

                while (!Thread.interrupted()) {
                    Frame frame = grabber.grab();
                    if (frame == null) {
                        break;
                    }
                    if (frame.image != null) {
                        Image image = SwingFXUtils.toFXImage(converter.convert(frame), null);
                        Platform.runLater(() -> {
                            imageView.setImage(image);
                        });
                    } else if (frame.samples != null) {
                        FloatBuffer channelSamplesFloatBuffer = (FloatBuffer) frame.samples[0];
                        channelSamplesFloatBuffer.rewind();

                        ByteBuffer outBuffer = ByteBuffer.allocate(channelSamplesFloatBuffer.capacity() * 2);

                        for (int i = 0; i < channelSamplesFloatBuffer.capacity(); i++) {
                            short val = (short)((double) channelSamplesFloatBuffer.get(i) * SC16);
                            outBuffer.putShort(val);
                        }

                        /**
                         * We need this because soundLine.write ignores
                         * interruptions during writing.
                         */
                        try {
                            executor.submit(() -> {
                                soundLine.write(outBuffer.array(), 0, outBuffer.capacity());
                                outBuffer.clear();
                            }).get();
                        } catch (InterruptedException interruptedException) {
                            Thread.currentThread().interrupt();
                        }
                    }
                }
                executor.shutdownNow();
                executor.awaitTermination(10, TimeUnit.SECONDS);
                soundLine.stop();
                grabber.stop();
                grabber.release();
                Platform.exit();
            } catch (Exception exception) {
                LOG.log(Level.SEVERE, null, exception);
                System.exit(1);
            }
        });
        playThread.start();
    }

    @Override
    public void stop() throws Exception
    {
        playThread.interrupt();
    }
}
person Teocci    schedule 07.11.2017

Поскольку данные, которые вы получаете в buftemp[], находятся в этом формате AV_SAMPLE_FMT_FLTP, вы должны изменить их на формат AV_SAMPLE_FMT_S16, используя SwrContext, и тогда ваша проблема будет решена.

person Bikash Sahani    schedule 10.05.2018