16,548
社区成员




char *filename = "C:\\Users\\admin\\Desktop\\hzw.mp4";
char *outfilename = "C:\\Users\\admin\\Desktop\\test.flv";
AVFormatContext *pFormatCtxDec, *pFormatCtxEnc;
AVCodecContext *pVCodecCtxDec,*pACodecCtxDec, *pVCodecCtxEnc,*pACodecCtxEnc;
AVCodec *pVCodecDec, *pACodecDec,*pVCodecEnc,*pACodecEnc;
AVFrame *pFrameDec, *pFrameEnc;
AVOutputFormat *pOutputFormat;
AVStream *video_st,*audio_st;
int i, videoStream,audioStream;
int outbuf_size,out_size;
uint8_t *outbuf;
AVPacket packet;
int frameFinished,frames=0;
av_register_all();
if(av_open_input_file(&pFormatCtxDec, filename, NULL, 0, NULL)!=0)
return ; // Couldn't open file
if(av_find_stream_info(pFormatCtxDec)<0)
return ; // Couldn't find stream information
videoStream=-1;
audioStream=-1;
for(i=0; i<pFormatCtxDec->nb_streams; i++) {
if(pFormatCtxDec->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
{
videoStream=i;
}
if(pFormatCtxDec->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
{
audioStream=i;
}
}
if(videoStream==-1 || audioStream==-1)
return ; // Didn't find a video stream
pVCodecCtxDec=pFormatCtxDec->streams[videoStream]->codec;
pACodecCtxDec=pFormatCtxDec->streams[audioStream]->codec;
// Find the decoder for the video stream
pVCodecDec=avcodec_find_decoder(pVCodecCtxDec->codec_id);
pACodecDec=avcodec_find_decoder(pACodecCtxDec->codec_id);
if(pVCodecDec==NULL || pACodecDec==NULL)
return ;
if(avcodec_open(pVCodecCtxDec, pVCodecDec)<0)
return ; // Could not open codec
if(avcodec_open(pACodecCtxDec, pACodecDec)<0)
return ; // Could not open codec
pFrameDec = avcodec_alloc_frame();
if(pFrameDec == NULL)
return ;
pOutputFormat = av_guess_format(NULL, outfilename, NULL);
if (pOutputFormat == NULL)
return;
pFormatCtxEnc = avformat_alloc_context();
if (pFormatCtxEnc == NULL)
return;
pFormatCtxEnc->oformat = pOutputFormat;
sprintf_s(pFormatCtxEnc->filename, "%s", outfilename);
video_st = av_new_stream(pFormatCtxEnc, 0); // 0 for video
audio_st = av_new_stream(pFormatCtxEnc, 1); // 1 for audio
pVCodecCtxEnc = video_st->codec;
pACodecCtxEnc = audio_st->codec;
pVCodecCtxEnc->codec_id = pOutputFormat->video_codec;
pACodecCtxEnc->codec_id = pOutputFormat->audio_codec;
pVCodecCtxEnc->codec_type = AVMEDIA_TYPE_VIDEO;
pACodecCtxEnc->codec_type = AVMEDIA_TYPE_AUDIO;
pACodecCtxEnc->sample_fmt = AV_SAMPLE_FMT_S16;
pACodecCtxEnc->bit_rate = 64000;
pACodecCtxEnc->sample_rate = 44100;
pACodecCtxEnc->channels = 2;
if (pOutputFormat->flags & AVFMT_GLOBALHEADER)
pACodecCtxEnc->flags |= CODEC_FLAG_GLOBAL_HEADER;
pVCodecCtxEnc->bit_rate = 200000;
pVCodecCtxEnc->width = pVCodecCtxDec->width;
pVCodecCtxEnc->height = pVCodecCtxDec->height;
pVCodecCtxEnc->time_base.den = 25;
pVCodecCtxEnc->time_base.num = 1;
pVCodecCtxEnc->pix_fmt = PIX_FMT_YUV420P;
pVCodecCtxEnc->gop_size = 12; /* emit one intra frame every ten frames */
//pVCodecCtxEnc->gop_size = pVCodecCtxDec->gop_size;
if (pVCodecCtxEnc->codec_id == CODEC_ID_MPEG1VIDEO){
/* needed to avoid using macroblocks in which some coeffs overflow
this doesnt happen with normal video, it just happens here as the
motion of the chroma plane doesnt match the luma plane */
pVCodecCtxEnc->mb_decision=2;
}
// some formats want stream headers to be seperate
if (pOutputFormat->flags & AVFMT_GLOBALHEADER)
pVCodecCtxEnc->flags |= CODEC_FLAG_GLOBAL_HEADER;
//if(!strcmp(pFormatCtxEnc->oformat->name, "mp4") || !strcmp(pFormatCtxEnc->oformat->name, "mov") || !strcmp(pFormatCtxEnc->oformat->name, "3gp"))
// pCodecCtxEnc->flags |= CODEC_FLAG_GLOBAL_HEADER;
// set the output parameters (must be done even if no parameters).
if (av_set_parameters(pFormatCtxEnc, NULL) < 0) {
return;
}
// find the video encoder
pVCodecEnc = avcodec_find_encoder(pVCodecCtxEnc->codec_id);
if (pVCodecEnc == NULL)
return;
pACodecEnc = avcodec_find_encoder(pACodecCtxEnc->codec_id);
if(pACodecEnc == NULL)
return;
// open it
if (avcodec_open(pVCodecCtxEnc, pVCodecEnc) < 0) {
return;
}
if (avcodec_open(pACodecCtxEnc, pACodecEnc) < 0) {
return;
}
if (!(pFormatCtxEnc->oformat->flags & AVFMT_RAWPICTURE)) {
/* allocate output buffer */
/* XXX: API change will be done */
outbuf_size = 500000;
outbuf = (uint8_t*)av_malloc(outbuf_size);
}
pFrameEnc= avcodec_alloc_frame();
// open the output file, if needed
if (!(pOutputFormat->flags & AVFMT_NOFILE)) {
if (url_fopen(&pFormatCtxEnc->pb, outfilename, URL_WRONLY) < 0) {
//printf(stderr, "Could not open '%s'\n", filename);
return;
}
}
// write the stream header, if any
av_write_header(pFormatCtxEnc);
int out_size_a = AVCODEC_MAX_AUDIO_FRAME_SIZE;
uint8_t * inbuf = (uint8_t *)av_malloc(out_size_a);
uint8_t * pinbuf = NULL;
int ob_size = FF_MIN_BUFFER_SIZE;
uint8_t * outbuf_a = (uint8_t *)av_malloc(ob_size);
int inputSampleSize = pACodecCtxDec->frame_size * 2 * pACodecCtxDec->channels;//获取Sample大小
//int outputSampleSize = oCodecCtx->frame_size * 2 * oCodecCtx->channels;//获取输出Sample大小
uint8_t * pktdata = NULL;
int pktsize = 0;
int len = 0;
av_init_packet(&packet);
// Read frames and save frames to disk
//double audio_pts,video_pts;
while(av_read_frame(pFormatCtxDec, &packet)>=0)
{
// Is this a packet from the video stream?
if(packet.stream_index==videoStream)
{
// Decode video frame
avcodec_decode_video2(pVCodecCtxDec, pFrameDec, &frameFinished, &packet);
// Did we get a video frame?
if(frameFinished)
{
frames++;
pFrameEnc->data[0] = pFrameDec->data[0];
pFrameEnc->data[1] = pFrameDec->data[1];
pFrameEnc->data[2] = pFrameDec->data[2];
pFrameEnc->linesize[0] = pFrameDec->linesize[0];
pFrameEnc->linesize[1] = pFrameDec->linesize[1];
pFrameEnc->linesize[2] = pFrameDec->linesize[2];
if (pFormatCtxEnc->oformat->flags & AVFMT_RAWPICTURE) {
/* raw video case. The API will change slightly in the near
futur for that */
AVPacket pkt;
av_init_packet(&pkt);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index= video_st->index;
pkt.data= (uint8_t *)pFrameEnc;
pkt.size= sizeof(AVPicture);
av_write_frame(pFormatCtxEnc, &pkt);
} else {
// encode the image
out_size = avcodec_encode_video(pVCodecCtxEnc, outbuf, outbuf_size, pFrameEnc);
// if zero size, it means the image was buffered
if (out_size != 0) {
AVPacket pkt;
av_init_packet(&pkt);
if (video_st->codec->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(video_st->codec->coded_frame->pts, video_st->codec->time_base, video_st->time_base);
//pkt.pts= pCodecCtxEnc->coded_frame->pts;
if(pVCodecCtxEnc->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index= video_st->index;
pkt.data= outbuf;
pkt.size= out_size;
// write the compressed frame in the media file
av_write_frame(pFormatCtxEnc, &pkt);
}
}
}
}
// Free the packet that was allocated by av_read_frame
if(packet.stream_index==audioStream)
{
pktdata = packet.data;
pktsize = packet.size;
while(pktsize>0)
{
out_size_a = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
//解码
int len = avcodec_decode_audio3(pACodecCtxDec, (short*)inbuf,&out_size_a,&packet);
if (len < 0)
{
break;
}
if(out_size_a > 0)
{
pinbuf = inbuf;
for (i=0;i<out_size_a;i+=inputSampleSize)
{
AVPacket pkt;
av_init_packet(&pkt);
ob_size = FF_MIN_BUFFER_SIZE;
pkt.size= avcodec_encode_audio(pACodecCtxEnc, outbuf_a, ob_size, (short *)pinbuf);
if (pACodecCtxEnc->coded_frame && pACodecCtxEnc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(pACodecCtxEnc->coded_frame->pts, pACodecCtxEnc->time_base, audio_st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index= audio_st->index;
pkt.data= outbuf_a;
/* write the compressed frame in the media file */
if (av_write_frame(pFormatCtxEnc, &pkt) != 0) {
break;
}
pinbuf += inputSampleSize;
}
}
pktsize -= len;
pktdata += len;
}
}
av_free_packet(&packet);
}
// get the delayed frames
for(; out_size; i++) {
out_size = avcodec_encode_video(pVCodecCtxEnc, outbuf, outbuf_size, NULL);
if (out_size != 0) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.pts= pVCodecCtxEnc->coded_frame->pts;
if(pVCodecCtxEnc->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index= video_st->index;
pkt.data= outbuf;
pkt.size= out_size;
// write the compressed frame in the media file
av_write_frame(pFormatCtxEnc, &pkt);
}
}
// Close the codec
avcodec_close(pVCodecCtxDec);
avcodec_close(pACodecCtxDec);
avcodec_close(pVCodecCtxEnc);
avcodec_close(pACodecCtxEnc);
// Free the YUV frame
av_free(pFrameDec);
av_free(pFrameEnc);
av_free(outbuf);
av_free(outbuf_a);
// write the trailer, if any
av_write_trailer(pFormatCtxEnc);
for(i = 0; i < pFormatCtxEnc->nb_streams; i++) {
av_freep(&pFormatCtxEnc->streams[i]->codec);
av_freep(&pFormatCtxEnc->streams[i]);
}
if (!(pOutputFormat->flags & AVFMT_NOFILE)) {
/* close the output file */
url_fclose(pFormatCtxEnc->pb);
}
av_free(pFormatCtxEnc);
av_close_input_file(pFormatCtxDec);