有几点须注意,
-
不要让硬解码器自已绘制表面,也就是AMediaCodec_configure传入的surface应设为空。否则运行时间长了,会出现“weak global reference table overflow”的崩机错误。
-
我之前文章里也说过了,不要静态链编libmediandk.so,老的安卓机上没有这个库,要动态检测加载,详细过程见之后代码。
-
AMediaCodec_dequeueInputBuffer不是每一次都返回成功,如果失败了而丢弃h264数据帧,则最终的播放效果就时不时出现花屏,正确处理见之后代码。
-
硬解码器解出的数据默认可能是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_;
}; |
#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