2020年9月29日 星期二

Android ffmpeg 使用

Outline

1. Video Decode
2. Video Encode

3. Audio Decode
4. Audio Encode

5. libyuv (YUV scaling & Convert ) 比ffmpeg 快


p.s. GoldWave 撥pcm , g711


-------------------------------------------------

  • 1. Video Decode


AVCodec *vCodec265 = NULL;
AVCodec *vCodec264 = NULL;
vCodec265 = avcodec_find_decoder(AV_CODEC_ID_HEVC);    //265
vCodec264 = avcodec_find_decoder(AV_CODEC_ID_H264); //264
AVCodecContext *vCodecCtxarr[32];// 16 for h264 ;  16 for h265
  • h265

vCodecCtxarr[nal_ch+16] = avcodec_alloc_context3(vCodec265);
vCodecCtxarr[nal_ch+16]->flags |= AV_CODEC_CAP_DELAY;
vCodecCtxarr[nal_ch+16]->skip_frame = AVDISCARD_BIDIR;
vCodecCtxarr[nal_ch+16]->skip_idct = AVDISCARD_NONREF;
vCodecCtxarr[nal_ch+16]->skip_loop_filter = AVDISCARD_NONREF;
vCodecCtxarr[nal_ch+16]->thread_count = 1;
open codec:

avcodec_open2(vCodecCtxarr[nal_ch+16], vCodec265, NULL)


  • h264
vCodecCtxarr[nal_ch] = avcodec_alloc_context3(vCodec264);
vCodecCtxarr[nal_ch]->flags |= AV_CODEC_CAP_DELAY;
vCodecCtxarr[nal_ch]->skip_frame = AVDISCARD_BIDIR;
vCodecCtxarr[nal_ch]->skip_idct = AVDISCARD_NONREF;
vCodecCtxarr[nal_ch]->skip_loop_filter = AVDISCARD_NONREF;
vCodecCtxarr[nal_ch]->thread_count = 1;
open deoce:
avcodec_open2(vCodecCtxarr[nal_ch], vCodec264, NULL)

--------------------decode stream 切換 vCodecCtxarr[ch]  or  vCodecCtxarr[ch+16]----------------

*input data:
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = (unsigned char*) nalData;
pkt.size = nal_length;
*deocode:

AVFrame * pFrame = av_frame_alloc();
int consumed_bytes = avcodec_decode_video2(vCodecCtxarr[nal_ch], pFrame, &got_picture,  &pkt);

轉換format (非必要) , yuv -> RBG565

img_convert_ctx = sws_getContext(
vCodecCtxarr[nal_ch]->width, vCodecCtxarr[nal_ch]->height,
vCodecCtxarr[nal_ch]->pix_fmt, vCodecCtxarr[nal_ch]->width,
vCodecCtxarr[nal_ch]->height,
AV_PIX_FMT_RGB565, SWS_FAST_BILINEAR, NULL, NULL, NULL);

*close codec




  • 2. Video Encode
avcodec_flush_buffers(vCodecCtxarr[nal_ch+16]);
avcodec_free_context(&vCodecCtxarr[nal_ch+16]);
vCodecCtxarr[nal_ch+16] = NULL;
av_free(vCodecCtxarr[nal_ch]);



  • 其他如 AVFrame 存為yuv 420:

FILE *pfout = NULL;
void yuv420p_save(AVFrame *pFrame, int mWidth,int mLeight)
{
int i = 0;

int width = mWidth, height = mLeight;
int height_half = height / 2, width_half = width / 2;
int y_wrap = pFrame->linesize[0];
int u_wrap = pFrame->linesize[1];
int v_wrap = pFrame->linesize[2];

unsigned char *y_buf = pFrame->data[0];
unsigned char *u_buf = pFrame->data[1];
unsigned char *v_buf = pFrame->data[2];
LOGE("qtParserTest....................... real width=%d,height= %d",width,height);
LOGE("qtParserTest....................... y_wrap= %d,u_wrap= %d,v_wrap= %d",y_wrap,u_wrap,v_wrap);

//if height=360,width=640,*3/2=> total 345600;y_wrap=640
//save y
for (i = 0; i < height; i++)
fwrite(y_buf + i * y_wrap, 1, width, pfout);//230400 height*width

//--------------for N12 uv uv;u_wrap=320
// for (i = 0; i < height_half; i++)
// fwrite(u_buf + i * u_wrap, 1, width, pfout);//115200 height_half*width

//-----------------below to for I420
//save u
for (i = 0; i < height_half; i++)//57600 height_half*width_half
fwrite(u_buf + i * u_wrap, 1, width_half, pfout);


//save v
for (i = 0; i < height_half; i++)//57600
fwrite(v_buf + i * v_wrap, 1, width_half, pfout);
//460800
fflush(pfout);
}

  • 3. Audio Decode  (g726 , aac) g711 用轉表方式


AVCodec        *m_pcodec;
AVCodecContext *m_pavCtx;
SwrContext *m_pswrCtx;
  • aac:
m_pcodec = avcodec_find_decoder(AV_CODEC_ID_AAC);
m_pavCtx = avcodec_alloc_context3(m_pcodec);
m_pavCtx->channels = 1;
m_pavCtx->sample_rate = i_sample_hz;
m_pavCtx->channel_layout = 1;

avcodec_open2(m_pavCtx, m_pcodec, NULL)

resample:

m_pswrCtx = swr_alloc_set_opts( NULL,
m_pavCtx->channel_layout,
AV_SAMPLE_FMT_S16,
m_pavCtx->sample_rate,
m_pavCtx->channels,
AV_SAMPLE_FMT_FLTP,
m_pavCtx->sample_rate,
0,
NULL);

output&decode:
AVPacket packet;
av_init_packet(&packet);

packet.size = buffer_size;
packet.data = data;
uint8_t *audio_buf = new uint8_t[10240];
AVFrame *frame = av_frame_alloc();
int len = avcodec_decode_audio4(m_pavCtx, frame, &got_frame, &packet);
int ret = swr_convert(m_pswrCtx, &audio_buf, frame->nb_samples,
(const uint8_t **) frame->extended_data, frame->nb_samples);
m_fun_notify(m_penv, (unsigned char *) audio_buf, frame->linesize[0] / 4);

  • g726:

m_pcodec = avcodec_find_decoder(AV_CODEC_ID_ADPCM_G726);
m_pavCtx->channels = 1;
m_pavCtx->sample_rate = 8000;
m_pavCtx->bit_rate = (ms32CodeType * 8);
m_pavCtx->bits_per_coded_sample = ms32CodeType ;
avcodec_open2(m_pavCtx, m_pcodec, NULL)


output &decode :

AVPacket packet;
av_init_packet(&packet);

packet.size = buffer_size;
packet.data = data;
uint8_t *audio_buf = new uint8_t[10240];
AVFrame *frame = av_frame_alloc();
int len = avcodec_decode_audio4(m_pavCtx, frame, &got_frame, &packet);
out:
dst_len=av_samples_get_buffer_size(NULL, m_pavCtx->channels,frame->nb_samples, AV_SAMPLE_FMT_S16, 1);
frame->data[0], dst_len

close:
avcodec_close(m_pavCtx);
av_free(m_pavCtx);
swr_free(&m_pswrCtx);

-----------------------------------



沒有留言:

張貼留言