原doc/sample/avio_reading.c
主要是如何自己处理文件,处理文件流,感觉用处不大
最后输出基本信息
extern "C"{ #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavformat/avio.h> #include <libavutil/file.h> }; #pragma comment(lib,"avformat.lib") #pragma comment(lib,"avutil.lib") #pragma comment(lib,"avcodec.lib") struct buffer_data {
uint8_t *ptr; //文件中对应位置指针 size_t size; ///文件当前指针到末尾数据大小 }; //将文件中数据拷贝至缓冲区,同时文件指针位置偏移,数据大小改变 static int read_packet(void *opaque, uint8_t *buf, int buf_size){ struct buffer_data *bd = (struct buffer_data *)opaque;
buf_size = FFMIN(buf_size, bd->size);
printf("ptr:%p size:%u\n", bd->ptr, bd->size); /* copy internal buffer data to buf */
memcpy(buf, bd->ptr, buf_size);
bd->ptr += buf_size;
bd->size -= buf_size; return buf_size; } int main(int argc, char *argv[]){
AVFormatContext*fmt_ctx=NULL;
AVIOContext*avio_ctx=NULL;
uint8_t*buffer=NULL;
uint8_t*avio_ctx_buffer=NULL;
size_t buffer_size,avio_ctx_buffer_size=4096; const char*input_filename="test.mkv"; struct buffer_data bd={0}; int ret=0; //注册所有支持的代码,能使用的都使用,方便,也可以按需注册自己所需的部分 av_register_all(); //类似于UNIX下的mmap函数所实现的功能,返回文件开始指针,文件大小 //文件过大,有3,4个G也能正常使用?? //经测试,并不耗内存,可视为UNIX下的文件映射 ret=av_file_map(input_filename,&buffer,&buffer_size,0,NULL); if(ret<0){
printf("av_file_map Err:%d\n",ret); goto end; } // printf("filesize:%d\n",buffer_size); bd.ptr=buffer;
bd.size=buffer_size; //初始化文件格式的结构体,就是分配内存,以后获取或设置编码格式都可以用这结构体管理,应该是当中的成员 if(!(fmt_ctx=avformat_alloc_context())){ //失败返回内存错误ENOMEM ret=AVERROR(ENOMEM); goto end; } //分配内存,可以自己设置缓冲大小 if(!(avio_ctx_buffer=(uint8_t*)av_malloc(avio_ctx_buffer_size))){
ret=AVERROR(ENOMEM); goto end; } //估计跟内存管理有关,avio_ctx_buffer是缓冲区,avio_ctx_buffer_size是缓冲区大小 //bd是文件,read_packet是读取函数 //avio_ctx->buffer=avio_ctx_buffer if(!(avio_ctx=avio_alloc_context(avio_ctx_buffer,avio_ctx_buffer_size,0, &bd,&read_packet,NULL,NULL))){
ret=AVERROR(ENOMEM); goto end; } //指针位置一样 //printf("%p %p\n",avio_ctx_buffer,avio_ctx->buffer); //设置IO管理 fmt_ctx->pb=avio_ctx; //跟metadata中avformat_open_input(&fmt_ctx,filename,NULL,NULL)等效 //这里都是自已去配置初始化相关信息,最后也要自己去清理 ret=avformat_open_input(&fmt_ctx,NULL,NULL,NULL); if(ret<0){
printf("Open Err\n"); goto end; } /* //metadata中代码在这一样可以用,输出一样,主要输出格式 AVDictionaryEntry*tag=NULL; while ((tag=av_dict_get(fmt_ctx->metadata,"",tag,AV_DICT_IGNORE_SUFFIX))){ printf("%s=%s\n",tag->key,tag->value); } */
ret=avformat_find_stream_info(fmt_ctx,NULL); if(ret<0){
printf("Could not find stream information\n"); goto end; } //输出基本信息,这里input_filename,只是用来显示文件名,无实际用处 //可随意换成其他字符串,不影响 //包含av_dict_getn内容,还有音视频编码信息 av_dump_format(fmt_ctx, 0, input_filename, 0);
end:
avformat_close_input(&fmt_ctx); if (avio_ctx) { //应该就是av_free(&avio_ctx_buffer),但位置不对 //两者相差0x1960 //printf("%p %p\n",avio_ctx_buffer,avio_ctx->buffer); av_freep(&avio_ctx->buffer);
av_freep(&avio_ctx); }
av_file_unmap(buffer, buffer_size);
printf("RET:%d\n",ret);
system("PAUSE"); return ret; }