9

これは私の最初の質問なので、何か見逃していたら教えてください!

Android API 16 の新しい Media Codec 実装を使用してビデオをデコードし、フレームを送信してテクスチャとして適用できるようにします (テクスチャ部分は既に完了しています)。したがって、スタックからの助けを借りて次のコードを思いつきましたが、戻っrunOutputBuffer()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 ) );
    }

}

}

4

1 に答える 1

9

James さん、Stack Overflow へようこそ (質問者として)!

私は MediaCodec クラスをいじろうとしましたが、ひどく制限されており、文書化も不十分です。ただし、Cedric Fung によるこのかなり堅実な投稿(および彼のリンクされた github) を確認してください。彼の github プロジェクトは、API-17 (JellyBean 4.2) 以降のデバイスですぐに動作するはずです。

そこから何を変更する必要があるかを判断できると確信していますが、前にほのめかしたように、API の現在のレベルでは柔軟性が制限されています。

特定の問題に関しては、メディア デコーダーの呼び出しで UI をロックしていると思いますが、これはお勧めできません。アクティブになるまで複数回呼び出されます。

これが役に立てば幸いです(質問してから数か月が経ちましたが)!

于 2013-03-26T21:10:49.087 に答える