//具体可以参考 FFmpeg 中 doc/APIchanges 中的记录.2016-04-21 - 7fc329e - lavc 57.37.100 - avcodec.hAdd a new audio/video encoding and decoding API with decoupled inputand output -- avcodec_send_packet(), avcodec_receive_frame(),avcodec_send_frame() and avcodec_receive_packet().
/*** Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet()* to retrieve buffered output packets.** @param avctx codec context* @param[in] frame AVFrame containing the raw audio or video frame to be encoded.* Ownership of the frame remains with the caller, and the* encoder will not write to the frame. The encoder may create* a reference to the frame data (or copy it if the frame is* not reference-counted).* It can be NULL, in which case it is considered a flush* packet. This signals the end of the stream. If the encoder* still has packets buffered, it will return them after this* call. Once flushing mode has been entered, additional flush* packets are ignored, and sending frames will return* AVERROR_EOF.** For audio:* If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame* can have any number of samples.* If it is not set, frame->nb_samples must be equal to* avctx->frame_size for all frames except the last.* The final frame may be smaller than avctx->frame_size.* @return 0 on success, otherwise negative error code:* AVERROR(EAGAIN): input is not accepted in the current state - user* must read output with avcodec_receive_packet() (once* all output is read, the packet should be resent, and* the call will not fail with EAGAIN).* AVERROR_EOF: the encoder has been flushed, and no new frames can* be sent to it* AVERROR(EINVAL): codec not opened, refcounted_frames not set, it is a* decoder, or requires flush* AVERROR(ENOMEM): failed to add packet to internal queue, or similar* other errors: legitimate encoding errors*/intavcodec_send_frame(AVCodecContext *avctx,const AVFrame *frame);
/*** Read encoded data from the encoder.** @param avctx codec context* @param avpkt This will be set to a reference-counted packet allocated by the* encoder. Note that the function will always call* av_packet_unref(avpkt) before doing anything else.* @return 0 on success, otherwise negative error code:* AVERROR(EAGAIN): output is not available in the current state - user* must try to send input* AVERROR_EOF: the encoder has been fully flushed, and there will be* no more output packets* AVERROR(EINVAL): codec not opened, or it is a decoder* other errors: legitimate encoding errors*/intavcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
/** Copyright (c) 2001 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.*//*** @file* video encoding with libavcodec API example** @example encode_video.c*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<libavcodec/avcodec.h>#include<libavutil/opt.h>#include<libavutil/imgutils.h>staticvoidencode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,FILE *outfile){int ret;/* send the frame to the encoder */if(frame)printf("Send frame %3"PRId64"\n", frame->pts);ret =avcodec_send_frame(enc_ctx, frame);if(ret <0){fprintf(stderr,"Error sending a frame for encoding\n");exit(1);}while(ret >=0){ret =avcodec_receive_packet(enc_ctx, pkt);if(ret ==AVERROR(EAGAIN)|| ret == AVERROR_EOF)return;elseif(ret <0){fprintf(stderr,"Error during encoding\n");exit(1);}printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);fwrite(pkt->data,1, pkt->size, outfile);av_packet_unref(pkt);}}intmain(int argc,char**argv){constchar*filename,*codec_name;const AVCodec *codec;AVCodecContext *c=NULL;int i, ret, x, y;FILE *f;AVFrame *frame;AVPacket *pkt;uint8_t endcode[]={0,0,1,0xb7};if(argc <=2){fprintf(stderr,"Usage: %s <output file> <codec name>\n", argv[0]);exit(0);}filename = argv[1];codec_name = argv[2];/* find the mpeg1video encoder */codec =avcodec_find_encoder_by_name(codec_name);if(!codec){fprintf(stderr,"Codec '%s' not found\n", codec_name);exit(1);}c =avcodec_alloc_context3(codec);if(!c){fprintf(stderr,"Could not allocate video codec context\n");exit(1);}pkt =av_packet_alloc();if(!pkt)exit(1);/* put sample parameters */c->bit_rate =400000;/* resolution must be a multiple of two */c->width =352;c->height =288;/* frames per second */c->time_base =(AVRational){1,25};c->framerate =(AVRational){25,1};/* emit one intra frame every ten frames* check frame pict_type before passing frame* to encoder, if frame->pict_type is AV_PICTURE_TYPE_I* then gop_size is ignored and the output of encoder* will always be I frame irrespective to gop_size*/c->gop_size =10;c->max_b_frames =1;c->pix_fmt = AV_PIX_FMT_YUV420P;if(codec->id == AV_CODEC_ID_H264)av_opt_set(c->priv_data,"preset","slow",0);/* open it */ret =avcodec_open2(c, codec,NULL);if(ret <0){fprintf(stderr,"Could not open codec: %s\n",av_err2str(ret));exit(1);}f =fopen(filename,"wb");if(!f){fprintf(stderr,"Could not open %s\n", filename);exit(1);}frame =av_frame_alloc();if(!frame){fprintf(stderr,"Could not allocate video frame\n");exit(1);}frame->format = c->pix_fmt;frame->width = c->width;frame->height = c->height;ret =av_frame_get_buffer(frame,0);if(ret <0){fprintf(stderr,"Could not allocate the video frame data\n");exit(1);}/* encode 1 second of video */for(i =0; i <25; i++){fflush(stdout);/* make sure the frame data is writable */ret =av_frame_make_writable(frame);if(ret <0)exit(1);/* prepare a dummy image *//* Y */for(y =0; y < c->height; y++){for(x =0; x < c->width; x++){frame->data[0][y * frame->linesize[0]+ x]= x + y + i *3;}}/* Cb and Cr */for(y =0; y < c->height/2; y++){for(x =0; x < c->width/2; x++){frame->data[1][y * frame->linesize[1]+ x]=128+ y + i *2;frame->data[2][y * frame->linesize[2]+ x]=64+ x + i *5;}}frame->pts = i;/* encode the image */encode(c, frame, pkt, f);}/* flush the encoder */encode(c,NULL, pkt, f);/* add sequence end code to have a real MPEG file */if(codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO)fwrite(endcode,1,sizeof(endcode), f);fclose(f);avcodec_free_context(&c);av_frame_free(&frame);av_packet_free(&pkt);return0;}
✨个人主页: Anmia.🎉所属专栏: C Language 🎃操作环境: Visual Studio 2019 版本 本篇目的是面向编程新手,没接触过编程的人。以及C进阶的导读。 内容是C语言重要知识点的简单解释,不做详解。给…