//初始化解封装和编解码
av_register_all();
avcodec_register_all();
//2、初始化网络
avformat_network_init();
AVFormatContext *avc = NULL;
char path[] = "/sdcard/test.mp4";
int result = avformat_open_input(&avc, path, 0, 0);
if (result != 0) {
return env->NewStringUTF("打开失败");
}
int videoStream = 0;
int audioStream = 0;
for (int i = 0; i < avc->nb_streams; ++i) {
AVStream *as = avc->streams[i];
if (as->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
//视频数据
}
else if (as->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audioStream = i;
//音频数据
}
}
//av_find_best_stream 例如音频数据
audioStream = av_find_best_stream(avc, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
AVStream *as = avc->streams[audioStream];
AVPacket *pkt = av_packet_alloc();
AVFrame *frame = av_frame_alloc();
for (;;) {
int re = av_read_frame(avc, pkt);
if (re != 0) {
LOGW("读取到结尾");
continue;
}
}
avcodec_find_decoder 查找解码器
//1、查找解码器
AVCodec *vcodec = avcodec_find_decoder(avc->streams[videoStream]->codecpar->codec_id);
//2、解码器环境空间初始化
AVCodecContext *vc = avcodec_alloc_context3(vcodec);
//可以将AVStream参数直接复制到AVCodec中,默认单线程
avcodec_parameters_to_context(vc, avc->streams[videoStream]->codecpar);
//设置线程数
vc->thread_count = 1;//线程数
//3、打开解码器
result = avcodec_open2(vc, 0, 0);
if (result != 0) {//如果失败
return env->NewStringUTF("avcodec_open2 failed");
}
//4、开始解码
//4.1发送到线程中解码
result = avcodec_send_packet(vc, pkt);
//4.2 要用for循环 保证能收到所有的数据
result = avcodec_receive_frame(vc, frame);
通过名称查找解码器:avcodec_find_decoder_by_name,例如
//其他和1.5.1一样
AVCodec *vcodec = = avcodec_find_decoder_by_name("h264_mediacodec");
//1、声明像素格式转换上下文
SwsContext *sctx = NULL;
int outWidth = 1280;
int outHeight = 720;
char *rgb = new char[1920 * 1080 * 4];//将空间复制给界面
//2、初始化像素格式转换上下文,在获取帧的for循环中操作
sctx = sws_getCachedContext(sctx,
frame->width,frame->height,(AVPixelFormat) frame->format,
outWidth, outHeight,AV_PIX_FMT_RGBA,
SWS_FAST_BILINEAR,0, 0, 0);
//3、数据转换
uint8_t *data[AV_NUM_DATA_POINTERS] = {0};
data[0] = (uint8_t *) rgb;
int lines[AV_NUM_DATA_POINTERS] = {0};//一行宽度的大小
lines[0] = outWidth * 4;//AV_PIX_FMT_RGBA 根据传进的像素格式获取大小
int h = sws_scale(sctx,(const uint8_t **) frame->data,
frame->linesize, 0,frame->height,
data, lines);
//1.创建频重采样上下文初始化
char *pcm = new char[48000 * 4 * 2];
SwrContext *srctx = swr_alloc();
//2.设置上下文
srctx = swr_alloc_set_opts(srctx,
//输出声道数
av_get_default_channel_layout(ac->channels),
//输出格式
AV_SAMPLE_FMT_S16,
//输入样本率不变
ac->sample_rate,
//输入声道数
av_get_default_channel_layout(ac->channels),
//输入声道数
ac->sample_fmt,
//输出样本率
ac->sample_rate,
0, 0);
//3.初始化上下文
result = swr_init(srctx);
//4,在获取帧的for循环中操作
uint8_t *out[2] = {0};//输出交错类型,非平面类型
out[0] = (uint8_t *) pcm;
//音频重采样
int len = swr_convert(srctx,
out, frame->nb_samples,
(const uint8_t **) frame->data, frame->nb_samples);
delete rgb;
delete pcm;
//释放内存
av_packet_unref(pkt);
//关闭上下文
avformat_close_input(&avc);