FFMPEG4.0オーディオデコードは、カプセル化を解除
FFMPEGはオーディオパッケージをエンコード
最新のFFMPEG 4.0(4.X)に基づいて、次の関数法:
この記事は、からの画像データ、ビデオファイルを抽出する方法について話した画像データやファイルに保存されます。
デコードとオーディオに似たカプセル解除手順、次のように:
ビデオのファイル形式情報をお読みください。
fmt_ctx = avformat_alloc_context();
avformat_open_input(&fmt_ctx,input,NULL,NULL);
avformat_find_stream_info(fmt_ctx,NULL);
2.ビデオストリームを取得します。
int st_index = av_find_best_stream(fmt_ctx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
LOGV("st_index = %d\n",st_index);
AVStream *st = fmt_ctx->streams[st_index];
3.準備し、デコードコンテキスト×××
AVCodec *codec = avcodec_find_decoder(st->codecpar->codec_id);
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
コンテキストおよびオープン×××4.コピーした映像ストリーム・パラメータ×××
avcodec_parameters_to_context(codec_ctx,st->codecpar);
avcodec_open2(codec_ctx,codec,NULL);
5.ビデオフォーマット、幅と高さの情報を読みます
int width = codec_ctx->width;
int height = codec_ctx->height;
enum AVPixelFormat pixel_fmt = codec_ctx->pix_fmt;
前記画像記憶アプリケーション
uint8_t *dst_buf[4] = {0};
int dst_linesize[4];
int size = av_image_alloc(dst_buf,dst_linesize,width,height,pixel_fmt,1);
パケット及びフレーム7は、元のデータが復号されたデータの後に格納されている述べ
AVFrame *frame = av_frame_alloc();
AVPacket *packet = av_packet_alloc();
8.リード・データ、ビデオのみデータへのアクセス
int ret = av_read_frame(fmt_ctx,packet);
//读取到的packet不仅仅是图像数据,还有音频、字幕等数据。
if(packet->stream_index != st_index)
{
continue;
}
9.送信データが復号化されret = avcodec_send_packet(codec_ctx,packet);
た生データ10.が受信デコード、これは反復プロセスであり、パケットは、いくつかのフレームを復号することができます
ret = avcodec_receive_frame(codec_ctx,frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) //packet解码完了,需要sent
break;
if(ret < 0) {
return 1;
}
注意:フレームは、(この素晴らしい映像を体験してはならない)、このような状況の広いまたは高のfmt形式の変更があるかもしれません、コードの背後にあるプロセスがこのケースを考慮していない受信
if(frame->width != width || frame->height != height || frame->format != pixel_fmt)
{
LOGV("eeeeeeeeeeeee");
}
前記データフレームのコピーは、予め用意dst_bufすることです。配列として見ポインタの二次元配列。av_image_copy(dst_buf,dst_linesize,frame->data,frame->linesize,pixel_fmt,width,height);
ファイルに書き込まれたデータ12。fwrite(dst_buf[0],1,size,out_file);
ここでは、コードが失敗した場合を考慮していない、最後はちょうどコア全体の復号処理をマスターするために、リリース、およびフラッシュなし×××に例を係合しない、完全なサンプルコードを投稿。
/*
* demuxing_decode_video.c
*
* Created on: 2019年1月8日
* Author: deanliu
*/
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
static char log_buf[1024*8];
#define LOGV(...) av_log(NULL,AV_LOG_VERBOSE,__VA_ARGS__)
void ffmpeg_log_callback(void* ptr, int level, const char* fmt, va_list vl)
{
static int print_prefix = 1;
av_log_format_line(ptr,level,fmt,vl,log_buf,sizeof(log_buf),&print_prefix);
fprintf(stderr,"%s",log_buf);
}
int main()
{
av_log_set_callback(ffmpeg_log_callback);
char *input = "E:/测试音视频/12种格式视频/test.avi";
char *output = "d:/video.v";
FILE *out_file = fopen(output,"wb");
AVFormatContext *fmt_ctx;
fmt_ctx = avformat_alloc_context();
avformat_open_input(&fmt_ctx,input,NULL,NULL);
avformat_find_stream_info(fmt_ctx,NULL);
int st_index = av_find_best_stream(fmt_ctx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
LOGV("st_index = %d\n",st_index);
AVStream *st = fmt_ctx->streams[st_index];
AVCodec *codec = avcodec_find_decoder(st->codecpar->codec_id);
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codec_ctx,st->codecpar);
avcodec_open2(codec_ctx,codec,NULL);
int width = codec_ctx->width;
int height = codec_ctx->height;
enum AVPixelFormat pixel_fmt = codec_ctx->pix_fmt;
uint8_t *dst_buf[4] = {0};
int dst_linesize[4];
int size = av_image_alloc(dst_buf,dst_linesize,width,height,pixel_fmt,1);
AVFrame *frame = av_frame_alloc();
AVPacket *packet = av_packet_alloc();
while(1)
{
LOGV("READ\n");
int ret = av_read_frame(fmt_ctx,packet);
if(ret < 0){
LOGV("ret = %d\n",ret);
break;
}
if(packet->stream_index != st_index)
{
continue;
}
LOGV("SENT\n");
ret = avcodec_send_packet(codec_ctx,packet);
if(ret < 0){
return 1;
}
while(ret >= 0)
{
LOGV("receiver\n");
ret = avcodec_receive_frame(codec_ctx,frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
if(ret < 0) {
return 1;
}
if(frame->width != width || frame->height != height || frame->format != pixel_fmt)
{
LOGV("eeeeeeeeeeeee");
}
av_image_copy(dst_buf,dst_linesize,frame->data,frame->linesize,pixel_fmt,width,height);
LOGV("dst_buf = %d,%d,%d,%d\n",dst_buf[2][0],dst_buf[1][1],dst_buf[0][2],dst_buf[0][3]);
fwrite(dst_buf[0],1,size,out_file);
}
}
LOGV("dst_linesize = %d,%d,%d,%d\n",dst_linesize[0],dst_linesize[1],dst_linesize[2],size);
printf("Play the output video file with the command:\n"
"ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n",
av_get_pix_fmt_name(pixel_fmt), width, height,
output);
LOGV("END!!");
fclose(out_file);
return 0;
}