Android Media Codec 视频解码

2024-01-30

这是我的第一个问题,如果我遗漏了什么,请告诉我!

使用 Android API 16 的新媒体编解码器实现来尝试解码视频,以便我可以发送要作为纹理应用的帧(纹理部分已经完成)。所以我在堆栈外的一些帮助下想出了以下代码,但在runOutputBuffer() my outputBufIndex正在回来-1(或者在我提供的无限循环中-1作为超时)任何人都可以帮忙解决这个问题,和/或提供关于从那里去哪里的任何建议吗?

感谢您的帮助,这是我的代码:

public MediaDecoder( BPRenderView bpview )
{

    surface = bpview;
    extractor = new MediaExtractor( );
    extractor.setDataSource( filePath );
    format = extractor.getTrackFormat( 0 );
    mime = format.getString( MediaFormat.KEY_MIME );
    createDecoder( );
    runInputBuffer( );

}

public void createDecoder( )
{

    codec = MediaCodec.createDecoderByType( "video/avc" );
    // format =extractor.getTrackFormat( 0 );
    Log.d( LOG_TAG, "Track Format: " + mime );
    // format.setInteger( MediaFormat.KEY_BIT_RATE, 125000 );
    // format.setInteger( MediaFormat.KEY_FRAME_RATE, 15 );
    // format.setInteger( MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar );
    // format.setInteger( MediaFormat.KEY_I_FRAME_INTERVAL, 5 );
    codec.configure( format, null, null, 0 );
    codec.start( );

    codecInputBuffers = codec.getInputBuffers( );
    codecOutputBuffers = codec.getOutputBuffers( );
    extractor.selectTrack( 0 );
}

public void runInputBuffer( )
{
    // This should take in the entire video and put it in the input buffer
    int inputBufIndex = codec.dequeueInputBuffer( -1 );
    if( inputBufIndex >= 0 )
    {
        ByteBuffer dstBuf = codecInputBuffers[ inputBufIndex ];

        int sampleSize = extractor.readSampleData( dstBuf, 0 );
        Log.d( "Sample Size", String.valueOf( sampleSize ) );
        long presentationTimeUs = 0;
        if( sampleSize < 0 )
        {
            sawInputEOS = true;
            sampleSize = 0;
        }
        else
        {
            presentationTimeUs = extractor.getSampleTime( );
        }
        Log.d( LOG_TAG, "Input Buffer" );
        Log.d( "InputBufIndex:", String.valueOf( inputBufIndex ) );
        Log.d( "PresentationTimeUS", String.valueOf( presentationTimeUs ) );
        codec.queueInputBuffer( inputBufIndex, 0, // offset
                sampleSize, presentationTimeUs, sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0 );
        if( !sawInputEOS )
        {
            Log.d( "Extractor", " Advancing" );
            extractor.advance( );

        }
    }
    runOutputBuffer( );
}

public void runOutputBuffer( )
{
    BufferInfo info = new BufferInfo( );

    final int res = codec.dequeueOutputBuffer( info, -1 );

    Log.d( "RES: ", String.valueOf( res ) );
    if( res >= 0 )
    {
        int outputBufIndex = res;
        ByteBuffer buf = codecOutputBuffers[ outputBufIndex ];
        final byte[ ] chunk = new byte[ info.size ];
        buf.get( chunk ); // Read the buffer all at once
        buf.clear( ); // ** MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN

        if( chunk.length > 0 )
        {
            Log.d( "Chunk: ", String.valueOf( chunk.length ) );

            surface.setTexture( chunk, 320, 240 );

            // mAudioTrack.write( chunk, 0, chunk.length );
            // do the things
        }
        codec.releaseOutputBuffer( outputBufIndex, false /* render */);

        if( ( info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM ) != 0 )
        {
            sawOutputEOS = true;
        }
    }
    else if( res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED )
    {
        codecOutputBuffers = codec.getOutputBuffers( );
    }
    else if( res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED )
    {
        final MediaFormat oformat = codec.getOutputFormat( );
        Log.d( LOG_TAG, "Output format has changed to " + oformat );
        // mAudioTrack.setPlaybackRate( oformat.getInteger( MediaFormat.KEY_SAMPLE_RATE ) );
    }

}

}


James,欢迎来到 Stack Overflow(作为提问者)!

我尝试玩弄 MediaCodec 类,它非常有限并且记录很少。然而,看看这个漂亮的实心柱 http://vec.io/posts/android-hardware-decoding-with-mediacodec(及其链接的 github)作者:Cedric Fung。他的 github 项目应该可以在 API-17 (JellyBean 4.2)+ 设备上开箱即用。

我确信您可以从那里确定需要更改的内容,尽管正如我之前提到的,在当前 API 级别的情况下,您的灵活性有限。

关于您的具体问题,我认为您正在使用媒体解码器调用锁定 UI,这是不建议的,您应该采用线程方法,而不是设置 -1 作为超时,而是将超时设置为 10000 并允许它被多次调用直到它被激活。

希望这会有所帮助(尽管你问这个问题已经过去几个月了)!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Media Codec 视频解码 的相关文章

随机推荐

  • 在 docker-compose 文件中启用“progress plain”

    当我使用运行构建时docker compose build progress plain 它在构建过程中显示比默认 BuildKit 输出更有用的信息 有没有办法将简单的进度选项嵌入到 docker compose yml 文件本身中 这样
  • 在 CSV 中搜索值 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有 csv 文件和一个值 我想搜索
  • Python - Pandas 每组随机采样

    我有一个与此非常相似的数据帧 但有数千个值 import numpy as np import pandas as pd Setup fake data np random seed 3 1415 df pd DataFrame Class
  • 纯函数是幂等的吗?

    每个纯函数都是幂等的吗 如果我没有在官方看到这个声明我不会问这么疯狂的问题Angular js 教程 https docs angularjs org guide filter creating custom filters 过滤函数应该是
  • Xamarin:发生地理定位错误:未经授权

    我正在尝试获取当前位置 并在 UWP 和 iOS 上工作 但在 Andriod 上运行时 它显示未处理的异常 Plugin Geolocator Abstractions GeolocationException 发生地理定位错误 未经授权
  • 列表视图按日期分组 Dart

    我一直在尝试获取按日期排序的一些消息 但没有成功 我尝试过不同的软件包 例如分组列表 https pub dev packages grouped list and 粘性标题 https pub dev packages sticky he
  • 当文本字段随着您的输入而变化时更改跨度

    我想要文本span字段更改为input字段变化live 所以我有一个input field
  • python 命名空间与包:将包设为默认命名空间

    我有一个具有总体命名空间的项目 其中包含包 这是文件夹结构 pypackage pypackage lt Source code for use in this project bin lt Module Cli entry point i
  • 在 contentplaceholder 中添加标题会添加第二个空标题标签

    我的母版页的 head 标签中有一个 contentplaceholder 因为我希望页面的标题能够代表当前页面的功能 并且因为我希望将标题翻译成用户的语言 所以我在页面头部的 contentplaceholder 中添加了一个标题标签 一
  • WPF CommandParameter 绑定和 canExecute

    我有一个树视图项目的模板
  • 取消引用 R dplyr 函数内的函数列表

    我试图将函数列表传递给 dplyrsummerize at函数并收到警告 library tidyverse library purrr p lt c 0 2 0 5 0 8 p names lt map chr p paste0 x 10
  • 检查重复项,对它们求和并在求和后删除一行

    我有一个包含一些重复项的数据框 我想对有重复项的两列的行进行求和 然后删除不需要的行 这是数据的示例 Year ID Lats Longs N n c id 2015 200 30 5417 20 5254 150 30 4142 2015
  • 如何从XAML引用嵌入式资源?

    我有几个图像想要嵌入到 exe 中 当我设置构建行动 to 嵌入式资源我在代码中发现了资源不可用的错误 并要求我将构建操作设置为Resource 我尝试了几种不同的方法
  • 如何创建和使用Java Card库包?

    正如您可能知道的 正如中提到的Java 卡开发套件用户指南为Java Card平台编写大型应用程序的关键是将代码划分为单独的包单元 软件包最重要的限制是最大组件大小为 64KB 对于 方法组件 如果应用程序的方法组件的大小超过 64KB 那
  • 使用名称中的变量从values/colors.xml中检索颜色(R.color.name + 变量)

    我的 color xml 中有一个颜色列表 它们的名称均采用 tColor1 tColor2 tColor3 等格式 我想在 for to do 循环中使用循环整数作为名称的一部分来检索它们 所以我有 for int i 0 i lt nu
  • 如何在UITableView后面添加MKMapKit?就像 svpply 一样

    这样 cell就可以覆盖MKMapView了 当表格向下滚动时 MKMapView 可以被触摸 如何 特别感谢 1 为表格视图添加标题视图 320px高度 背景色清晰 2 将MKMapView放在UITableView下 3 覆盖表视图的h
  • Eclipse hibernate pojo 生成包括外键

    我一直在遵循一个关于使用 hibernate 从 mysql 数据库生成 pojo 的优秀指南 人们可以在这里找到指南以供参考 使用 hibernate 生成 pojo http www javacodegeeks com 2013 10
  • 特定 std::bind 返回的数据类型到底是什么?

    首先我不得不说我必须知道 std bind 返回的数据类型 我有一个结构体定义为 typedef struct UINT ID CString NAME boost any Func auto doesn t work here CALLB
  • swagger-ui.html 400 错误请求

    我已将 swagger 集成到我的 Spring Boot 项目中 所有 swagger 端点都工作正常 但是 product swagger ui html给出 400 错误 经过一些调试 我发现两个端点之间存在冲突 在我的 applic
  • Android Media Codec 视频解码

    这是我的第一个问题 如果我遗漏了什么 请告诉我 使用 Android API 16 的新媒体编解码器实现来尝试解码视频 以便我可以发送要作为纹理应用的帧 纹理部分已经完成 所以我在堆栈外的一些帮助下想出了以下代码 但在runOutputBu