extern "C"
{
#include "libavformat\avformat.h"
#include "libavdevice\avdevice.h"
#include "libswscale\swscale.h"
};
int pNewWidth = 0;
int pNewHeight = 0;
void SetVideoFrame(AVCodecContext *pCodecCtx, AVFrame *pFrame, AVFrame *pNewFrame, int pNewWidth, int pNewHeight)
{
pNewFrame->linesize[0] = pNewWidth;
pNewFrame->linesize[1] = pNewWidth / 2;
pNewFrame->linesize[2] = pNewWidth / 2;
struct SwsContext *pSwsCtx = NULL;
pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, pNewWidth, pNewHeight, PIX_FMT_YUV420P, SWS_SINC, NULL, NULL, NULL);
if (pSwsCtx == NULL)
return;
sws_scale(pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pNewFrame->data, pNewFrame->linesize);
sws_freeContext(pSwsCtx);
}
int VideoDecode(char *VideoName, char* YUVName)
{
FILE *fw = fopen(YUVName, "wb");
if (fw == NULL)
return -1;
AVFormatContext *pFormatContext = NULL;
pFormatContext = avformat_alloc_context();
if (avformat_open_input(&pFormatContext, VideoName, NULL, NULL) != 0)
return -2;
if (avformat_find_stream_info(pFormatContext, NULL) < 0)
{
avformat_close_input(&pFormatContext);
return -3;
}
AVCodecContext *pCodecContext = NULL;
pCodecContext = pFormatContext->streams[0]->codec;
AVCodec *pCodec = NULL;
pCodec = avcodec_find_decoder(pCodecContext->codec_id);
if (pCodec == NULL)
{
avformat_close_input(&pFormatContext);
return -4;
}
if (avcodec_open2(pCodecContext, pCodec, NULL) < 0)
{
avformat_close_input(&pFormatContext);
return -5;
}
AVFrame *pFrame, *pFrameDispose;
pFrame = av_frame_alloc();
pFrameDispose = av_frame_alloc();
if ((pFrame == NULL) || (pFrameDispose == NULL))
{
avcodec_close(pCodecContext);
avformat_close_input(&pFormatContext);
return -6;
}
pNewWidth = pCodecContext->width;
pNewHeight = pCodecContext->height;
int DisposeSize = avpicture_get_size(PIX_FMT_YUV420P, pCodecContext->width, pCodecContext->height);
uint8_t *DisposeBuf = (uint8_t *)av_malloc(DisposeSize*sizeof(uint8_t));
avpicture_fill((AVPicture *)pFrameDispose, DisposeBuf, PIX_FMT_YUV420P, pCodecContext->width, pCodecContext->height);
AVPacket pPacket;
int got_picture_ptr = 0;
while (av_read_frame(pFormatContext, &pPacket) >= 0)
{
if (pPacket.stream_index == 0)
{
if (avcodec_decode_video2(pCodecContext, pFrame, &got_picture_ptr, &pPacket) >= 0)
{
if (got_picture_ptr)
{
SetVideoFrame(pCodecContext, pFrame, pFrameDispose, pCodecContext->width, pCodecContext->height);
fwrite(DisposeBuf, 1, DisposeSize, fw);
}
}
}
}
fclose(fw);
av_free(DisposeBuf);
av_frame_free(&pFrameDispose);
av_frame_free(&pFrame);
avcodec_close(pCodecContext);
avformat_close_input(&pFormatContext);
return 0;
}
int yuv420p_to_mp4(char* yuv420p_name, char* mp4_name)
{
FILE* fr_yuv420p = fopen(yuv420p_name, "rb");
if (fr_yuv420p == NULL)
return -1;
AVOutputFormat* pOutputFormat = av_guess_format(NULL, mp4_name, NULL);
if (pOutputFormat == NULL)
{
fclose(fr_yuv420p);
return -2;
}
AVFormatContext* pFormatContext = avformat_alloc_context();
if (pFormatContext == NULL)
{
fclose(fr_yuv420p);
return -3;
}
pFormatContext->oformat = pOutputFormat;
strncpy(pFormatContext->filename, mp4_name, sizeof(pFormatContext->filename));
if (pOutputFormat->video_codec == AV_CODEC_ID_NONE)
{
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return -4;
}
AVStream* pStream = avformat_new_stream(pFormatContext, NULL);
if (pStream == NULL)
{
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return -5;
}
AVCodecContext* pCodecContext = pStream->codec;
pCodecContext->codec_id = pFormatContext->oformat->video_codec;
pCodecContext->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecContext->bit_rate = 400000;
pCodecContext->gop_size = 3;
pCodecContext->pix_fmt = PIX_FMT_YUV420P;
pCodecContext->width = pNewWidth;
pCodecContext->height = pNewHeight;
pCodecContext->time_base.num = 1;
pCodecContext->time_base.den = 10;
pCodecContext->me_range = 16;
pCodecContext->max_qdiff = 4;
pCodecContext->qcompress = 0.6;
if (pCodecContext->codec_id == AV_CODEC_ID_MPEG2VIDEO)
pCodecContext->max_b_frames = 2;
if (pCodecContext->codec_id == AV_CODEC_ID_MPEG1VIDEO)
pCodecContext->mb_decision = 2;
if (!strcmp(pFormatContext->oformat->name, "mp4") || !strcmp(pFormatContext->oformat->name, "mov") || !strcmp(pFormatContext->oformat->name, "3gp"))
pCodecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
AVCodec* pCodec = avcodec_find_encoder(pCodecContext->codec_id);
if (avcodec_open2(pCodecContext, pCodec, NULL) < 0)
{
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return -6;
}
if (avio_open(&pFormatContext->pb, mp4_name, AVIO_FLAG_WRITE) < 0)
{
avcodec_close(pCodecContext);
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return -7;
}
int video_outbuf_size = 0;
uint8_t* video_outbuf = NULL;
if (!(pFormatContext->oformat->flags & AVFMT_RAWPICTURE))
{
video_outbuf_size = 200000;
video_outbuf = (uint8_t*)av_malloc(video_outbuf_size);
}
int pFrameSize = avpicture_get_size(pCodecContext->pix_fmt, pCodecContext->width, pCodecContext->height);
uint8_t* pFrameBuf = (uint8_t*)av_malloc(pFrameSize);
AVFrame* pFrame = avcodec_alloc_frame();
if (pFrame == NULL)
{
avio_close(pFormatContext->pb);
avcodec_close(pCodecContext);
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return -8;
}
avpicture_fill((AVPicture *)pFrame, pFrameBuf, pCodecContext->pix_fmt, pCodecContext->width, pCodecContext->height);
pFrame->format = pCodecContext->pix_fmt;
pFrame->width = pCodecContext->width;
pFrame->height = pCodecContext->height;
if (avformat_write_header(pFormatContext, NULL) < 0)
{
av_free(pFrame);
av_free(pFrameBuf);
avio_close(pFormatContext->pb);
avcodec_close(pCodecContext);
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return -9;
}
while (1)
{
if (fread(pFrame->data[0], 1, pFrameSize, fr_yuv420p) != pFrameSize)
break;
pFrame->pts++;
int ReturnValue = 0, buf_size = 0;
AVPacket pPacket;
if (pFormatContext->oformat->flags & AVFMT_RAWPICTURE)
{
av_init_packet(&pPacket);
pPacket.flags |= AV_PKT_FLAG_KEY;
pPacket.stream_index = pStream->index;
pPacket.data = (uint8_t*)pFrame;
pPacket.size = sizeof(AVPicture);
ReturnValue = av_write_frame(pFormatContext, &pPacket);
}
else
{
buf_size = avcodec_encode_video(pCodecContext, video_outbuf, video_outbuf_size, pFrame);
if (buf_size > 0)
{
av_init_packet(&pPacket);
if (pCodecContext->coded_frame->key_frame)
pPacket.flags |= AV_PKT_FLAG_KEY;
pPacket.stream_index = pStream->index;
pPacket.data = video_outbuf;
pPacket.size = buf_size;
ReturnValue = av_write_frame(pFormatContext, &pPacket);
}
else
ReturnValue = 0;
}
if (ReturnValue != 0)
{
av_free_packet(&pPacket);
av_free(pFrame);
av_free(pFrameBuf);
avio_close(pFormatContext->pb);
avcodec_close(pCodecContext);
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return -10;
}
}
av_write_trailer(pFormatContext);
av_free(pFrame);
av_free(pFrameBuf);
avio_close(pFormatContext->pb);
avcodec_close(pCodecContext);
avformat_free_context(pFormatContext);
fclose(fr_yuv420p);
return 0;
}
int main()
{
av_register_all();
if (VideoDecode("20170105.avi", "20170105.yuv") != 0)
printf("VideoDecode fail\n");
if (yuv420p_to_mp4("20170105.yuv", "20170105.mp4") != 0)
printf("yuv420p_to_mp4 fail\n");
return 0;
}
- 1
- 2
前往页