zoukankan      html  css  js  c++  java
  • 最简单的基于FFmpeg的AVUtil样例 (AVLog, AVOption等)

    本文的演示样例程序记录了FFmpeg的libavutil中几种工具函数的用法:
    AVLog:日志输出
    AVOption (AVClass):选项设置
    AVDictionary:键值对存储
    ParseUtil:字符串解析

    几个libavutil的工具


    AVLog

    AVLog是FFmpeg的日志输出工具。在FFmpeg中全部的日志输出不是通过printf()函数而是通过av_log()函数。av_log()会终于调用fprintf(stderr,…)函数将日志内容输出到命令行界面上。可是在一些非命令行程序(MFC程序,Android程序等)中。av_log()调用的fprintf(stderr,…)就无法将日志内容显示出来了。

    对于这样的情况,FFmpeg提供了日志回调函数av_log_set_callback()。

    该函数能够指定一个自己定义的日志输出函数,将日志输出到指定的位置。


    以下的自己定义函数custom_output()将日志输出到了“simplest_ffmpeg_log.txt”文本中。


    void custom_output(void* ptr, int level, const char* fmt,va_list vl){
    	FILE *fp = fopen("simplest_ffmpeg_log.txt","a+");   
    	if(fp){   
    		vfprintf(fp,fmt,vl);
    		fflush(fp);
    		fclose(fp);
    	}   
    }

    在主函数中调用av_log_set_callback()设置一下该函数就能够了,例如以下所看到的。
    int main(int argc, char* argv[])
    {
    	av_log_set_callback(custom_output);
    	return 0;
    }

    此外。日志信息从重到轻分为Panic、Fatal、Error、Warning、Info、Verbose、Debug几个级别。以下的函数输出了几种不同级别的日志。


    void test_log(){
    	av_register_all();
    	AVFormatContext *obj=NULL;
    	obj=avformat_alloc_context();
    	printf("====================================
    ");
    	av_log(obj,AV_LOG_PANIC,"Panic: Something went really wrong and we will crash now.
    ");
    	av_log(obj,AV_LOG_FATAL,"Fatal: Something went wrong and recovery is not possible.
    ");
    	av_log(obj,AV_LOG_ERROR,"Error: Something went wrong and cannot losslessly be recovered.
    ");
    	av_log(obj,AV_LOG_WARNING,"Warning: This may or may not lead to problems.
    ");
    	av_log(obj,AV_LOG_INFO,"Info: Standard information.
    ");
    	av_log(obj,AV_LOG_VERBOSE,"Verbose: Detailed information.
    ");
    	av_log(obj,AV_LOG_DEBUG,"Debug: Stuff which is only useful for libav* developers.
    ");
    	printf("====================================
    ");
    	avformat_free_context(obj);
    }

    PS:该部分源码的解析能够參考文章《FFmpeg源码简单分析:日志输出系统(av_log()等)

    AVOption (AVClass)

    AVOption是FFmpeg的选项设置工具。与AVOption最相关的选项设置函数就是av_opt_set()了。AVOption的核心概念就是“依据字符串操作结构体的属性值”。比如以下代码中“#if”和“#else”之间代码的作用和“#else”和“#endif”之间代码的作用是一样的。
    #if TEST_OPT
    	av_opt_set(pCodecCtx,"b","400000",0);		//bitrate
    	//Another method
    	//av_opt_set_int(pCodecCtx,"b",400000,0);	//bitrate
    
    	av_opt_set(pCodecCtx,"time_base","1/25",0);	//time_base
    	av_opt_set(pCodecCtx,"bf","5",0);			//max b frame
    	av_opt_set(pCodecCtx,"g","25",0);			//gop
    	av_opt_set(pCodecCtx,"qmin","10",0);		//qmin/qmax
    	av_opt_set(pCodecCtx,"qmax","51",0);
    #else
    	pCodecCtx->time_base.num = 1;  
    	pCodecCtx->time_base.den = 25;  
    	pCodecCtx->max_b_frames=5;
    	pCodecCtx->bit_rate = 400000;  
    	pCodecCtx->gop_size=25;
    	pCodecCtx->qmin = 10;
    	pCodecCtx->qmax = 51;
    #endif
    

    同理。av_opt_get()能够将结构体的属性值以字符串的形式返回回来。

    比如以下这段代码就验证了av_opt_get()的作用:

    		char *val_str=(char *)av_malloc(50);
    
    		//preset: ultrafast, superfast, veryfast, faster, fast, 
    		//medium, slow, slower, veryslow, placebo
    		av_opt_set(pCodecCtx->priv_data,"preset","slow",0);
    		//tune: film, animation, grain, stillimage, psnr, 
    		//ssim, fastdecode, zerolatency
    		av_opt_set(pCodecCtx->priv_data,"tune","zerolatency",0);
    		//profile: baseline, main, high, high10, high422, high444
    		av_opt_set(pCodecCtx->priv_data,"profile","main",0);
    
    		//print
    		av_opt_get(pCodecCtx->priv_data,"preset",0,(uint8_t **)&val_str);
    		printf("preset val: %s
    ",val_str);
    		av_opt_get(pCodecCtx->priv_data,"tune",0,(uint8_t **)&val_str);
    		printf("tune val: %s
    ",val_str);
    		av_opt_get(pCodecCtx->priv_data,"profile",0,(uint8_t **)&val_str);
    		printf("profile val: %s
    ",val_str);
    		av_free(val_str);
    

    能够通过av_opt_find()获取结构体中随意选项的AVOption结构体。

    写了一个简单的函数读取该结构体中一些字段的值。


    void print_opt(const AVOption *opt_test){
    
    	printf("====================================
    ");
    	printf("Option Information:
    ");
    	printf("[name]%s
    ",opt_test->name);
    	printf("[help]%s
    ",opt_test->help);
    	printf("[offset]%d
    ",opt_test->offset);
    
    	switch(opt_test->type){
    	case AV_OPT_TYPE_INT:{
    		printf("[type]int
    [default]%d
    ",opt_test->default_val.i64);
    		break;
    						 }
    	case AV_OPT_TYPE_INT64:{
    		printf("[type]int64
    [default]%lld
    ",opt_test->default_val.i64);
    		break;
    						   }
    	case AV_OPT_TYPE_FLOAT:{
    		printf("[type]float
    [default]%f
    ",opt_test->default_val.dbl);
    		break;
    						   }
    	case AV_OPT_TYPE_STRING:{
    		printf("[type]string
    [default]%s
    ",opt_test->default_val.str);
    		break;
    							}
    	case AV_OPT_TYPE_RATIONAL:{
    		printf("[type]rational
    [default]%d/%d
    ",opt_test->default_val.q.num,opt_test->default_val.q.den);
    		break;
    							  }
    	default:{
    		printf("[type]others
    ");
    		break;
    			}
    	}
    
    	printf("[max val]%f
    ",opt_test->max);
    	printf("[min val]%f
    ",opt_test->min);
    
    	if(opt_test->flags&AV_OPT_FLAG_ENCODING_PARAM){
    		printf("Encoding param.
    ");
    	}
    	if(opt_test->flags&AV_OPT_FLAG_DECODING_PARAM){
    		printf("Decoding param.
    ");
    	}
    	if(opt_test->flags&AV_OPT_FLAG_AUDIO_PARAM){
    		printf("Audio param.
    ");
    	}
    	if(opt_test->flags&AV_OPT_FLAG_VIDEO_PARAM){
    		printf("Video param.
    ");
    	}
    	if(opt_test->unit!=NULL)
    		printf("Unit belong to:%s
    ",opt_test->unit);
    
    	printf("====================================
    ");
    }
    

    使用下列代码调用上面的函数就能够打印出AVOption结构体每一个字段的值。
    	const AVOption *opt=NULL;
    	opt=av_opt_find(pCodecCtx, "b", NULL, 0, 0);
    	print_opt(opt);
    	opt=av_opt_find(pCodecCtx, "g", NULL, 0, 0);
    	print_opt(opt);
    	opt=av_opt_find(pCodecCtx, "time_base", NULL, 0, 0);
    	print_opt(opt);

    以下代码能够打印出支持AVOption(即包括AVClass)的结构体的全部选项:
    void list_obj_opt(void *obj){
    	printf("Output some option info about object:
    ");
    	printf("Object name:%s
    ",(*(AVClass **) obj)->class_name);
    	printf("=====================================
    ");
    	printf("Video param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_VIDEO_PARAM,NULL);
    	printf("Audio param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_AUDIO_PARAM,NULL);
    	printf("Decoding param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_DECODING_PARAM,NULL);
    	printf("Encoding param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_ENCODING_PARAM,NULL);
    	printf("====================================
    ");
    }

    以下代码调用上面的函数就能够打印出AVFormatContext中的全部选项。
    void test_opt(){
    	av_register_all();
    	AVFormatContext *obj=NULL;
    	obj=avformat_alloc_context();
    	list_obj_opt(obj);
    	avformat_free_context(obj);
    }

    PS:该部分源码的解析能够參考文章《FFmpeg源码简单分析:结构体成员管理系统-AVClass》、《FFmpeg源码简单分析:结构体成员管理系统-AVOption》。

    AVDictionary

    AVDictionary是FFmpeg的键值对存储工具,FFmpeg常常使用AVDictionary设置/读取内部參数。以下这段代码记录了AVDictionary的用法。


    void test_avdictionary(){
    
    	AVDictionary *d = NULL;
    	AVDictionaryEntry *t = NULL;
    
    	av_dict_set(&d, "name", "lei xiaohua", 0);
    	av_dict_set(&d, "email", "leixiaohua1020@126.com", 0);
    	av_dict_set(&d, "school", "cuc", 0);
    	av_dict_set(&d, "gender", "man", 0);
    	av_dict_set(&d, "website", "http://blog.csdn.net/leixiaohua1020", 0);
    	//av_strdup()
    	char *k = av_strdup("location");
    	char *v = av_strdup("Beijing-China");
    	av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
    	printf("====================================
    ");
    	int dict_cnt= av_dict_count(d);
    	printf("dict_count:%d
    ",dict_cnt);
    	printf("dict_element:
    ");
    	while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
    		printf("key:%10s  |  value:%s
    ",t->key,t->value);
    	}
    
    	t = av_dict_get(d, "email", t, AV_DICT_IGNORE_SUFFIX);
    	printf("email is %s
    ",t->value);
    	printf("====================================
    ");
    	av_dict_free(&d);
    }

    ParseUtil

    ParseUtil是FFmpeg的字符串解析工具。

    它的分辨率解析函数av_parse_video_size()能够从形如“1920x1080”的字符串中解析出图像宽为1920,高为1080;它的帧率函数av_parse_video_rate()能够解析出帧率信息。它的时间解析函数则能够从形如“00:01:01”的字符串解析出时间的毫秒数。以下这段代码记录了ParseUtil的用法。

    void test_parseutil(){
    	char input_str[100]={0};
    	printf("========= Parse Video Size =========
    ");
    	int output_w=0;
    	int output_h=0;
    	strcpy(input_str,"1920x1080");
    	av_parse_video_size(&output_w,&output_h,input_str);
    	printf("w:%4d | h:%4d
    ",output_w,output_h);
    	strcpy(input_str,"vga");
    	//strcpy(input_str,"hd1080");
    	//strcpy(input_str,"ntsc");
    	av_parse_video_size(&output_w,&output_h,input_str);
    	printf("w:%4d | h:%4d
    ",output_w,output_h);
    	printf("========= Parse Frame Rate =========
    ");
    	AVRational output_rational={0,0};
    	strcpy(input_str,"15/1");
    	av_parse_video_rate(&output_rational,input_str);
    	printf("framerate:%d/%d
    ",output_rational.num,output_rational.den);
    	strcpy(input_str,"pal");
    	av_parse_video_rate(&output_rational,input_str);
    	printf("framerate:%d/%d
    ",output_rational.num,output_rational.den);
    	printf("=========== Parse Time =============
    ");
    	int64_t output_timeval;
    	strcpy(input_str,"00:01:01");
    	av_parse_time(&output_timeval,input_str,1);
    	printf("microseconds:%lld
    ",output_timeval);
    	printf("====================================
    ");
    }
    


    源码


    /**
     * 最简单的FFmpeg的AVUtil演示样例
     * Simplest FFmpeg AVUtil
     *
     * 雷霄骅 Lei Xiaohua
     * leixiaohua1020@126.com
     * 中国传媒大学/数字电视技术
     * Communication University of China / Digital TV Technology
     * http://blog.csdn.net/leixiaohua1020
     *
     * 本程序是FFmpeg中的libavutil的演示样例。眼下包括:
     * AVLog
     * AVOption (AVClass)
     * AVDictionary
     * ParseUtil
     *
     * This software is the example about FFmpeg's libavutil.
     * It contains:
     * AVLog
     * AVOption (AVClass)
     * AVDictionary
     * ParseUtil 
     *
     */
    
    #include <stdio.h>
    
    #define __STDC_CONSTANT_MACROS
    
    #ifdef _WIN32
    //Windows
    extern "C"
    {
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/opt.h"
    #include "libavutil/parseutils.h"
    #include "libavutil/avutil.h"
    };
    #else
    //Linux...
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavutil/opt.h>
    #include <libavutil/parseutils.h>
    #include <libavutil/avutil.h>
    #ifdef __cplusplus
    };
    #endif
    #endif
    
    
    #define TEST_OPT	1
    #define TEST_LOG	1
    #define TEST_DIC	0
    
    
    void list_obj_opt(void *obj){
    	printf("Output some option info about object:
    ");
    	printf("Object name:%s
    ",(*(AVClass **) obj)->class_name);
    	printf("=====================================
    ");
    	printf("Video param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_VIDEO_PARAM,NULL);
    	printf("Audio param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_AUDIO_PARAM,NULL);
    	printf("Decoding param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_DECODING_PARAM,NULL);
    	printf("Encoding param:
    ");
    	av_opt_show2(obj,stderr,AV_OPT_FLAG_ENCODING_PARAM,NULL);
    	printf("====================================
    ");
    }
    
    void test_opt(){
    	av_register_all();
    	AVFormatContext *obj=NULL;
    	obj=avformat_alloc_context();
    	list_obj_opt(obj);
    	avformat_free_context(obj);
    }
    
    
    void test_log(){
    	av_register_all();
    	AVFormatContext *obj=NULL;
    	obj=avformat_alloc_context();
    	printf("====================================
    ");
    	av_log(obj,AV_LOG_PANIC,"Panic: Something went really wrong and we will crash now.
    ");
    	av_log(obj,AV_LOG_FATAL,"Fatal: Something went wrong and recovery is not possible.
    ");
    	av_log(obj,AV_LOG_ERROR,"Error: Something went wrong and cannot losslessly be recovered.
    ");
    	av_log(obj,AV_LOG_WARNING,"Warning: This may or may not lead to problems.
    ");
    	av_log(obj,AV_LOG_INFO,"Info: Standard information.
    ");
    	av_log(obj,AV_LOG_VERBOSE,"Verbose: Detailed information.
    ");
    	av_log(obj,AV_LOG_DEBUG,"Debug: Stuff which is only useful for libav* developers.
    ");
    	printf("====================================
    ");
    	avformat_free_context(obj);
    }
    
    void print_opt(const AVOption *opt_test){
    
    	printf("====================================
    ");
    	printf("Option Information:
    ");
    	printf("[name]%s
    ",opt_test->name);
    	printf("[help]%s
    ",opt_test->help);
    	printf("[offset]%d
    ",opt_test->offset);
    
    	switch(opt_test->type){
    	case AV_OPT_TYPE_INT:{
    		printf("[type]int
    [default]%d
    ",opt_test->default_val.i64);
    		break;
    						 }
    	case AV_OPT_TYPE_INT64:{
    		printf("[type]int64
    [default]%lld
    ",opt_test->default_val.i64);
    		break;
    						   }
    	case AV_OPT_TYPE_FLOAT:{
    		printf("[type]float
    [default]%f
    ",opt_test->default_val.dbl);
    		break;
    						   }
    	case AV_OPT_TYPE_STRING:{
    		printf("[type]string
    [default]%s
    ",opt_test->default_val.str);
    		break;
    							}
    	case AV_OPT_TYPE_RATIONAL:{
    		printf("[type]rational
    [default]%d/%d
    ",opt_test->default_val.q.num,opt_test->default_val.q.den);
    		break;
    							  }
    	default:{
    		printf("[type]others
    ");
    		break;
    			}
    	}
    
    	printf("[max val]%f
    ",opt_test->max);
    	printf("[min val]%f
    ",opt_test->min);
    
    	if(opt_test->flags&AV_OPT_FLAG_ENCODING_PARAM){
    		printf("Encoding param.
    ");
    	}
    	if(opt_test->flags&AV_OPT_FLAG_DECODING_PARAM){
    		printf("Decoding param.
    ");
    	}
    	if(opt_test->flags&AV_OPT_FLAG_AUDIO_PARAM){
    		printf("Audio param.
    ");
    	}
    	if(opt_test->flags&AV_OPT_FLAG_VIDEO_PARAM){
    		printf("Video param.
    ");
    	}
    	if(opt_test->unit!=NULL)
    		printf("Unit belong to:%s
    ",opt_test->unit);
    
    	printf("====================================
    ");
    }
    
    int flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index)
    {
    	int ret;
    	int got_frame;
    	AVPacket enc_pkt;
    	if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
    		CODEC_CAP_DELAY))
    		return 0;
    	while (1) {
    		printf("Flushing stream #%u encoder
    ", stream_index);
    		enc_pkt.data = NULL;
    		enc_pkt.size = 0;
    		av_init_packet(&enc_pkt);
    		ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
    			NULL, &got_frame);
    		av_frame_free(NULL);
    		if (ret < 0)
    			break;
    		if (!got_frame){
    			ret=0;
    			break;
    		}
    		printf("Succeed to encode 1 frame!
    ");
    		/* mux encoded frame */
    		ret = av_write_frame(fmt_ctx, &enc_pkt);
    		if (ret < 0)
    			break;
    	}
    	return ret;
    }
    
    int encoder(){
    	AVFormatContext* pFormatCtx;
    	AVStream* video_st;
    	AVCodecContext* pCodecCtx;
    	AVCodec* pCodec;
    
    	uint8_t* picture_buf;
    	AVFrame* picture;
    	int size;
    	int ret;
    	AVPacket pkt;
    	int y_size;
    
    	FILE *in_file = fopen("ds_480x272.yuv", "rb");	//Input YUV data
    	int in_w=480,in_h=272;                          //Input width and height
    	//Frames to encode
    	int framenum=100;
    	const char* out_file = "ds.h264";	            //Output Filepath
    	//const char* out_file = "ds.ts";
    	//const char* out_file = "ds.hevc";
    	char temp_str[250]={0};
    
    	av_register_all();
    	
    	avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);
    
    	if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
    		printf("Failed to open output file!
    ");
    		return -1;
    	}
    
    	pCodec = avcodec_find_encoder(pFormatCtx->oformat->video_codec);
    	if (!pCodec) {
    		fprintf(stderr, "Codec not found.
    ");
    		return -1;
    	}
    	video_st = avformat_new_stream(pFormatCtx, pCodec);
    	video_st->time_base.num = 1; 
    	video_st->time_base.den = 25;  
    
    	if (video_st==NULL){
    		return -1;
    	}
    	//Param that must set
    	pCodecCtx = video_st->codec;
    	pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
    	pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
    	pCodecCtx->width = in_w;  
    	pCodecCtx->height = in_h;
    
    #if TEST_OPT
    	av_opt_set(pCodecCtx,"b","400000",0);		//bitrate
    	//Another method
    	//av_opt_set_int(pCodecCtx,"b",400000,0);	//bitrate
    
    	av_opt_set(pCodecCtx,"time_base","1/25",0);	//time_base
    	av_opt_set(pCodecCtx,"bf","5",0);			//max b frame
    	av_opt_set(pCodecCtx,"g","25",0);			//gop
    	av_opt_set(pCodecCtx,"qmin","10",0);		//qmin/qmax
    	av_opt_set(pCodecCtx,"qmax","51",0);
    #else
    	pCodecCtx->time_base.num = 1;  
    	pCodecCtx->time_base.den = 25;  
    	pCodecCtx->max_b_frames=5;
    	pCodecCtx->bit_rate = 400000;  
    	pCodecCtx->gop_size=25;
    	pCodecCtx->qmin = 10;
    	pCodecCtx->qmax = 51;
    #endif
    
    #if TEST_OPT
    	//list_obj_opt(pFormatCtx);
    	//list_obj_opt(pCodecCtx);
    	const AVOption *opt=NULL;
    	opt=av_opt_find(pCodecCtx, "b", NULL, 0, 0);
    	print_opt(opt);
    	opt=av_opt_find(pCodecCtx, "g", NULL, 0, 0);
    	print_opt(opt);
    	opt=av_opt_find(pCodecCtx, "time_base", NULL, 0, 0);
    	print_opt(opt);
    	//Get Option
    	//Get String
    	int64_t *val_str=(int64_t *)av_malloc(1*sizeof(int64_t));
    	av_opt_get(pCodecCtx,"b",0,(uint8_t **)&val_str);
    	printf("get bitrate(str):%s
    ",val_str);
    	av_free(val_str);
    	//Get int
    	int64_t val_int=0;
    	av_opt_get_int(pCodecCtx,"b",0,&val_int);
    	printf("get bitrate(int):%lld
    ",val_int);
    #endif
    
    	AVDictionary *param = 0;
    
    	//H.264
    	if(pCodecCtx->codec_id == AV_CODEC_ID_H264) {
    		char *val_str=(char *)av_malloc(50);
    		//List it
    		//list_obj_opt(pCodecCtx->priv_data);
    
    		//preset: ultrafast, superfast, veryfast, faster, fast, 
    		//medium, slow, slower, veryslow, placebo
    		av_opt_set(pCodecCtx->priv_data,"preset","slow",0);
    		//tune: film, animation, grain, stillimage, psnr, 
    		//ssim, fastdecode, zerolatency
    		av_opt_set(pCodecCtx->priv_data,"tune","zerolatency",0);
    		//profile: baseline, main, high, high10, high422, high444
    		av_opt_set(pCodecCtx->priv_data,"profile","main",0);
    
    		//print
    		av_opt_get(pCodecCtx->priv_data,"preset",0,(uint8_t **)&val_str);
    		printf("preset val: %s
    ",val_str);
    		av_opt_get(pCodecCtx->priv_data,"tune",0,(uint8_t **)&val_str);
    		printf("tune val: %s
    ",val_str);
    		av_opt_get(pCodecCtx->priv_data,"profile",0,(uint8_t **)&val_str);
    		printf("profile val: %s
    ",val_str);
    		av_free(val_str);
    
    #if TEST_DIC
    		av_dict_set(¶m, "preset", "slow", 0);  
    		av_dict_set(¶m, "tune", "zerolatency", 0);  
    		//av_dict_set(¶m, "profile", "main", 0);  
    #endif
    	}
    	//H.265
    	if(pCodecCtx->codec_id == AV_CODEC_ID_H265){
    		//list_obj_opt(pCodecCtx->priv_data);
    
    		//preset: ultrafast, superfast, veryfast, faster, fast, 
    		//medium, slow, slower, veryslow, placebo
    		av_opt_set(pCodecCtx->priv_data, "preset", "ultrafast", 0);
    		//tune: psnr, ssim, zerolatency, fastdecode
    		av_opt_set(pCodecCtx->priv_data, "tune", "zero-latency", 0);
    		//profile: main, main10, mainstillpicture
    		av_opt_set(pCodecCtx->priv_data,"profile","main",0);
    	}
    
    	if (avcodec_open2(pCodecCtx, pCodec,¶m) < 0){
    		printf("Failed to open encoder!
    ");
    		return -1;
    	}
    
    	picture = avcodec_alloc_frame();
    	size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
    	picture_buf = (uint8_t *)av_malloc(size);
    	avpicture_fill((AVPicture *)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
    
    	//Write File Header
    	avformat_write_header(pFormatCtx,NULL);
    
    	y_size = pCodecCtx->width * pCodecCtx->height;
    	av_new_packet(&pkt,y_size*3);
    
    	for (int i=0; i<framenum; i++){
    		//Read YUV
    		if (fread(picture_buf, 1, y_size*3/2, in_file) < 0){
    			printf("Failed to read YUV data!
    ");
    			return -1;
    		}else if(feof(in_file)){
    			break;
    		}
    		picture->data[0] = picture_buf;              // Y
    		picture->data[1] = picture_buf+ y_size;      // U 
    		picture->data[2] = picture_buf+ y_size*5/4;  // V
    		//PTS
    		picture->pts=i;
    		int got_picture=0;
    		//Encode
    		ret = avcodec_encode_video2(pCodecCtx, &pkt,picture, &got_picture);
    		if(ret < 0){
    			printf("Failed to encode!
    ");
    			return -1;
    		}
    		if (got_picture==1){
    			//printf("Succeed to encode 1 frame!
    ");
    			pkt.stream_index = video_st->index;
    			ret = av_write_frame(pFormatCtx, &pkt);
    			av_free_packet(&pkt);
    		}
    	}
    	//Flush Encoder
    	ret = flush_encoder(pFormatCtx,0);
    	if (ret < 0) {
    		printf("Flushing encoder failed
    ");
    		return -1;
    	}
    
    	//Write file trailer
    	av_write_trailer(pFormatCtx);
    
    	//Clean
    	if (video_st){
    		avcodec_close(video_st->codec);
    		av_free(picture);
    		av_free(picture_buf);
    	}
    	avio_close(pFormatCtx->pb);
    	avformat_free_context(pFormatCtx);
    
    	fclose(in_file);
    	return 0;
    }
    
    void custom_output(void* ptr, int level, const char* fmt,va_list vl){
    	FILE *fp = fopen("simplest_ffmpeg_log.txt","a+");   
    	if(fp){   
    		vfprintf(fp,fmt,vl);
    		fflush(fp);
    		fclose(fp);
    	}   
    }
    
    void test_parseutil(){
    	char input_str[100]={0};
    	printf("========= Parse Video Size =========
    ");
    	int output_w=0;
    	int output_h=0;
    	strcpy(input_str,"1920x1080");
    	av_parse_video_size(&output_w,&output_h,input_str);
    	printf("w:%4d | h:%4d
    ",output_w,output_h);
    	strcpy(input_str,"vga");
    	//strcpy(input_str,"hd1080");
    	//strcpy(input_str,"ntsc");
    	av_parse_video_size(&output_w,&output_h,input_str);
    	printf("w:%4d | h:%4d
    ",output_w,output_h);
    	printf("========= Parse Frame Rate =========
    ");
    	AVRational output_rational={0,0};
    	strcpy(input_str,"15/1");
    	av_parse_video_rate(&output_rational,input_str);
    	printf("framerate:%d/%d
    ",output_rational.num,output_rational.den);
    	strcpy(input_str,"pal");
    	av_parse_video_rate(&output_rational,input_str);
    	printf("framerate:%d/%d
    ",output_rational.num,output_rational.den);
    	printf("=========== Parse Time =============
    ");
    	int64_t output_timeval;
    	strcpy(input_str,"00:01:01");
    	av_parse_time(&output_timeval,input_str,1);
    	printf("microseconds:%lld
    ",output_timeval);
    	printf("====================================
    ");
    }
    
    void test_avdictionary(){
    
    	AVDictionary *d = NULL;
    	AVDictionaryEntry *t = NULL;
    
    	av_dict_set(&d, "name", "lei xiaohua", 0);
    	av_dict_set(&d, "email", "leixiaohua1020@126.com", 0);
    	av_dict_set(&d, "school", "cuc", 0);
    	av_dict_set(&d, "gender", "man", 0);
    	av_dict_set(&d, "website", "http://blog.csdn.net/leixiaohua1020", 0);
    	//av_strdup()
    	char *k = av_strdup("location");
    	char *v = av_strdup("Beijing-China");
    	av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
    	printf("====================================
    ");
    	int dict_cnt= av_dict_count(d);
    	printf("dict_count:%d
    ",dict_cnt);
    	printf("dict_element:
    ");
    	while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
    		printf("key:%10s  |  value:%s
    ",t->key,t->value);
    	}
    
    	t = av_dict_get(d, "email", t, AV_DICT_IGNORE_SUFFIX);
    	printf("email is %s
    ",t->value);
    	printf("====================================
    ");
    	av_dict_free(&d);
    }
    
    int main(int argc, char* argv[])
    {
    	int loglevel=av_log_get_level();
    	av_log_set_level(AV_LOG_DEBUG);
    	//av_log_set_flags(AV_LOG_PRINT_LEVEL);
    	//av_log_set_callback(custom_output);
    	test_log();
    
    	test_avdictionary();
    	test_parseutil();
    
    	//test_opt();
    
    	encoder();
    
    	return 0;
    }
    


    执行结果

    不同级别的AVLog日志输出后的结果:
     
    结构体中全部AVOption信息输出后的结果:
     
    AVDictionary演示样例输出的结果:
     
    ParseUtil演示样例输出的结果:
     
    编码的时候设置回调函数后输出到文本中的日志:
     

    下载


    Simplest FFmpeg AVUtil

    项目主页

    SourceForge:https://sourceforge.net/projects/simplestffmpegavutil/
    Github:https://github.com/leixiaohua1020/simplest_ffmpeg_avutil
    开源中国:http://git.oschina.net/leixiaohua1020/simplest_ffmpeg_avutil


    CSDN下载地址:http://download.csdn.net/detail/leixiaohua1020/8924311


    本程序是FFmpeg中的libavutil的演示样例,眼下包括:
    AVLog
    AVOption (AVClass)
    AVDictionary
    ParseUtil



  • 相关阅读:
    python提供的网络接口API和Linux Socket API间的关系探究 liushu
    业务领域建模Domain Modeling liushu
    分析一套源代码的代码规范和风格并讨论如何改进优化代码 liushu
    案例分析:设计模式与代码的结构特性 liushu
    如何提高程序员的键盘使用效率 liushu
    网络相关的命令工具研究报告 liushu
    用例建模Use Case Modeling liushu
    WdatePicker日历控件使用方法
    添加Web服务引用,服务引用,WCF服务开发
    JS大总结
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7029096.html
Copyright © 2011-2022 走看看