視頻解碼流程
流程圖:視頻解碼流程圖.png
注冊組件
av_register_all();打開文件
avformat_open_input();查找視頻流
avformat_find_stream_info();查找視頻解碼器
打開解碼器
avcodec_open2();讀取視頻壓縮數(shù)據(jù)
視頻解碼
關(guān)閉解碼器-〉解碼完成
示例:
+(void) ffmepgVideoDecode:(NSString*)inFilePath outFilePath:(NSString*)outFilePath{
av_register_all();
AVFormatContext *avformat_context = avformat_alloc_context();
const char *url = [inFilePath UTF8String];
int avformat_open_input_result = avformat_open_input(&avformat_context, url, NULL, NULL);
if (avformat_open_input_result != 0) {
NSLog(@"打開文件失斕几臁亡容!");
return;
}
int avformat_find_stream_info_result = avformat_find_stream_info(avformat_context, NULL);
if (avformat_find_stream_info_result < 0) {
NSLog(@"查找失斃殴亍!");
return;
}
int av_stream_index = -1;
for (int i = 0; i < avformat_context->nb_streams; ++i) {
if(avformat_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
av_stream_index = i;
break;
}
}
AVCodecContext *avcodec_context = avformat_context->streams[av_stream_index]->codec;
AVCodec *avcodec = avcodec_find_decoder(avcodec_context->codec_id);
int avcodec_open2_result = avcodec_open2(avcodec_context, avcodec, NULL);
if (avcodec_open2_result != 0) {
NSLog(@"打開解碼器失斎饪怠!");
return;
}
NSLog(@"解碼器名稱:%s",avcodec->name);
AVPacket *packet = (AVPacket*)av_malloc(sizeof(AVPacket));
AVFrame *avframe_in = av_frame_alloc();
int decode_result = -1;
struct SwsContext *swscontext = sws_getContext(avcodec_context->width,
avcodec_context->height,
avcodec_context->pix_fmt,
avcodec_context->width,
avcodec_context->height,
AV_PIX_FMT_YUV420P,
SWS_BICUBIC,
NULL,
NULL,
NULL);
AVFrame *avframe_yuv420p = av_frame_alloc();
int buffer_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P,
avcodec_context->width,
avcodec_context->height,
1);
uint8_t *out_buffer = (uint8_t*)av_malloc(buffer_size);
av_image_fill_arrays(avframe_yuv420p->data,
avframe_yuv420p->linesize,
out_buffer,
AV_PIX_FMT_YUV420P,
avcodec_context->width,
avcodec_context->height,
1);
int y_size,u_size,v_size;
const char *outfile = [outFilePath UTF8String];
FILE *file_yuv420p = fopen(outfile, "wb+");
if (file_yuv420p == NULL) {
NSLog(@"輸出文件打開失敗");
return;
}
int current_index = 0;
while (av_read_frame(avformat_context, packet) >= 0) {
if (packet->stream_index == av_stream_index){
avcodec_send_packet(avcodec_context, packet);
decode_result = avcodec_receive_frame(avcodec_context, avframe_in);
if (decode_result == 0) {
sws_scale(swscontext,
(const uint8_t *const *)avframe_in->data,
avframe_in->linesize,
0,
avcodec_context->height,
avframe_yuv420p->data,
avframe_yuv420p->linesize);
y_size = avcodec_context->width * avcodec_context->height;
u_size = y_size / 4;
v_size = y_size / 4;
fwrite(avframe_yuv420p->data[0], 1, y_size, file_yuv420p);
fwrite(avframe_yuv420p->data[1], 1, u_size, file_yuv420p);
fwrite(avframe_yuv420p->data[2], 1, v_size, file_yuv420p);
current_index ++;
NSLog(@"當前解碼第%d幀",current_index);
}
}
}
av_packet_free(&packet);
fclose(file_yuv420p);
av_frame_free(&avframe_in);
av_frame_free(&avframe_yuv420p);
free(out_buffer);
avcodec_close(avcodec_context);
avformat_free_context(avformat_context);
}