赞
踩
format_ctx->pb = avio_ctx;通过在媒体流上下文中指定AVIO上下文,在AVIO上下文中指定回调函数。当打开媒体流并调用av_read_frame就会调用read_packet。
完整代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <libavutil/frame.h> #include <libavutil/mem.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #define AVIO_BUF_SIZE 20480 static void print_sample_format(const AVFrame* frame) { printf("samplerate:%uHz\n",frame->sample_rate); printf("channel:%u\n",frame->channels); printf("format:%u\n",frame->format); } static int read_packet(void* opaque,uint8_t* buf,int buf_size) { FILE* in_file = (FILE*)opaque; int read_size = fread(buf,1,buf_size,in_file); printf("read packet size is:%u,buf_size is:%u\n",read_size,buf_size); } static void Decode(AVCodecContext *decode_ctx, AVPacket *packet, AVFrame *frame, FILE *outfile) { int result = avcodec_send_packet(decode_ctx,packet); while(result >= 0) { avcodec_receive_frame(decode_ctx,frame); int data_size = av_get_bytes_per_sample(decode_ctx->sample_fmt); for(int i = 0; i < frame->nb_samples; i++) { for(int ch = 0; ch < decode_ctx->channels; ch++) { fwrite(frame->data[ch] + data_size *i, 1, data_size, outfile); } } } } int main() { printf("Hello World!\n"); const char *in_file_name = "/home/yx/media_file/believe.mp4"; const char *out_file_name = "/home/yx/media_file/believe.aac"; FILE *in_file = NULL; FILE *out_file = NULL; in_file = fopen(in_file_name, "rb"); out_file = fopen(out_file_name, "wb"); uint8_t *io_buffer = av_malloc(AVIO_BUF_SIZE); AVIOContext *avio_ctx = avio_alloc_context(io_buffer, AVIO_BUF_SIZE, 0, (void *)in_file, read_packet, NULL, NULL); AVFormatContext *format_ctx = avformat_alloc_context(); format_ctx->pb = avio_ctx; // 回调函数 avformat_open_input(&format_ctx, NULL, NULL, NULL); AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_AAC); AVCodecContext *codec_ctx = avcodec_alloc_context3(codec); avcodec_open2(codec_ctx, codec, NULL); AVPacket *packet = av_packet_alloc(); AVFrame *frame = av_frame_alloc(); while (1) { if(av_read_frame(format_ctx, packet) < 0) // read_packet作为回调函数会触发 break; Decode(codec_ctx, packet, frame, out_file); // 不用添加ADTS头部,直接写到输出文件 } printf("read file finish\n"); Decode(codec_ctx, NULL, frame, out_file); fclose(in_file); fclose(out_file); av_free(io_buffer); av_frame_free(frame); av_packet_free(packet); avformat_close_input(&format_ctx); avcodec_free_context(&codec_ctx); printf("main finish\n"); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。