Android播放器-解码

  • 解封装
  • 软硬解码
  • 像素格式转换
  • 重采样
  • pts/dts
  • 同步策略

avcodec_find_decoder

avcodec_register_all(); // 注册所有的解码器
AVCodec *avcodec_find_decoder(enum AVCodecID id)
AVCodec 只是存放了解码器格式的配置信息
AVCodec *avcodec_find_decoder_by_name(const char *name)
avcodec_find_decoder_by_name("h264_mediacodec") // 用Android里面自带的解码模块,ARM CPU是一个集合,里面自带一个解码模块,其实就是调用了Android里面的java接口

AVCodecContext

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) // 可以不传解码器,只是创建的解码器上下文里面会没有解码器
void avcodec_free_context(AVCodecContext **avctx)

// 打开
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); // 如果AVCodecContext里面已经有解码器,就不需要传codec,options:参考/libavcodec/options_table.h

int thread_count; // 多线程
time_base // 时间的基数

avcodec_parameters_to_context

将codec的参数拷贝到context
avcodec_parameters_to_context(codec, p);

AVFrame

AVFrame *frame = av_frame_alloc();
void av_frame_free(AVFrame **frame);// 引用计数减一,并释放本身
int av_frame_ref(AVFrame *dst, const AVFrame *src); // 引用计数加一
AVFrame *av_frame_clone(const AVFrame *src); // 复制,并引用计数加一
void av_frame_unref(AVFrame *frame); // 直接引用计数减一

成员:
uint8_t *data[AV_NUM_DATA_POINTERS] // 可能是交叉模式或平面模式
int linesize[AV_NUM_DATA_POINTERS] // 视频表示一行数据大小,音频表示一个通道数据大小
int width;
int height;
int nb_samples; // 音频,表示单通道样本数量,一般1024
int64_t pts;
int64_t pkt_dts;
int sample_rate;
uint64_t channel_layout;
int channels;
int format; // AVPixelFormat AVSampleFormat

linesize

平面模式(因为有对齐的原因):

0 Y大小
1 U大小
2 V大小
3 NULL

0 左声道(planner)大小
1 右声道大小
2 NULL

0 RGB RGB RGB大小
1 NULL

avcodec_send_packet

int avcodec_send_packet(
AVCodecContext *avctx,
const AVPacket *avpkt);
// 调用完这个函数后,可以安全的释放avpkt,因为内部已经缓存了一个AVPacket空间

avcodec_receive_frame

int avcodec_receive_frame(
AVCodecContext *avctx,
AVFrame *frame);

可能前面几帧解不出来,获取的这一帧可能是之前的,怎么取出结尾中的几帧,也可能取到多个
打赏