NDK硬解h264

有几点须注意,

  1. 不要让硬解码器自已绘制表面,也就是AMediaCodec_configure传入的surface应设为空。否则运行时间长了,会出现“weak global reference table overflow”的崩机错误。
  2. 我之前文章里也说过了,不要静态链编libmediandk.so,老的安卓机上没有这个库,要动态检测加载,详细过程见之后代码。
  3. AMediaCodec_dequeueInputBuffer不是每一次都返回成功,如果失败了而丢弃h264数据帧,则最终的播放效果就时不时出现花屏,正确处理见之后代码。
  4. 硬解码器解出的数据默认可能是NV12格式也可能是YV12格式,不同的手机不一样,预先配置解码器的"color-format"为19,也没用。为了与ffmpeg解出的数据一致为YU12格式,统一地我们自已转。

以下是源码,摘选自EuhatRtsp开源软件,经历过长时间拷机运行没问题。其网址是:http://euhat.com/rtsp.html


DecoderHard.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#pragma once
 
#include "DecodeOp.h"
 
class AMediaCodec;
 
class EuhatDecoderHard : public EuhatDecoderBase
{
    int updateSpsAndPps();
 
    int spsChanged_;
    int ppsChanged_;
    char *sps_;
    char *pps_;
    int width_;
    int height_;
    int oriHeight_;
    int colorFormat_;
    int stride_;
    int sliceHeight_;
    int cropTop_;
    int cropBottom_;
    int cropLeft_;
    int cropRight_;
    int isCodecInited_;
    void *surface_;
    int surfaceChanged_;
 
public:
    EuhatDecoderHard();
    virtual ~EuhatDecoderHard();
 
    virtual int init(EuhatDecoderCallback callback, void *context);
    virtual int fini();
    virtual int updateSps(const char *sps);
    virtual int updatePps(const char *pps);
    virtual int updateWH(int width, int height);
    virtual int updateSurface(void *surface);
    virtual int decode(char *frame, int frameLen);
 
    static int canWork();
 
    AMediaCodec *mediaCodec_;
};

Read more