int mp4_to_yuv(char * input_path, char * output_path)
{
//1、注冊(cè)所有組件
av_register_all();
//2、打開(kāi)視頻文件
AVFormatContext *pFormatCtx = avformat_alloc_context();
if ((avformat_open_input(&pFormatCtx, input_path, NULL, NULL)) < 0)
{
printf("Cannot open input file");
return -1;
}
//3、獲取視頻信息
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Cannot find stream\n");
if(pFormatCtx)
avformat_free_context(pFormatCtx);
avformat_close_input(&pFormatCtx);
return -1;
}
//4、找到視頻流的位置
int video_stream_index = -1;
int i = 0;
for (; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
video_stream_index = i;
//av_log(pFormatCtx, AV_LOG_ERROR, "find the stream index %d.\n", video_stream_index);
//LOGE("find the stream index %d", video_stream_index);
break;
}
}
//5、獲取解碼器
AVCodecContext *pCodeCtx = pFormatCtx->streams[video_stream_index]->codec;
int width = pCodeCtx->width;
int height = pCodeCtx->height;
AVCodec *pCodec = avcodec_find_decoder(pCodeCtx->codec_id);
if (pCodec == NULL)
{
av_log(pFormatCtx, AV_LOG_ERROR, "Cannot find decoder.\n");
if(pFormatCtx)
avformat_free_context(pFormatCtx);
avformat_close_input(&pFormatCtx);
return -1;
}
//6、打開(kāi)解碼器
if (avcodec_open2(pCodeCtx, pCodec, NULL) < 0)
{
printf("Cannot open codec\n");
if(pFormatCtx)
avformat_free_context(pFormatCtx);
avformat_close_input(&pFormatCtx);
return -1;
}
//7、解析每一幀數(shù)據(jù)
int got_picture_ptr, frame_count = 1;
//壓縮數(shù)據(jù)
AVPacket *packet = (AVPacket *) av_malloc(sizeof(AVPacket));
//解壓縮數(shù)據(jù)
AVFrame *frame = av_frame_alloc();
AVFrame *yuvFrame = av_frame_alloc();
//將視頻轉(zhuǎn)換成指定的420P的YUV格式
//緩沖區(qū)分配內(nèi)存
uint8_t *out_buffer = (uint8_t *) av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodeCtx->width, pCodeCtx->height));
//初始化緩沖區(qū)
avpicture_fill((AVPicture *) yuvFrame, out_buffer, AV_PIX_FMT_YUV420P, pCodeCtx->width,
pCodeCtx->height);
//用于像素格式轉(zhuǎn)換或者縮放
struct SwsContext *sws_ctx = sws_getContext(pCodeCtx->width, pCodeCtx->height, pCodeCtx->pix_fmt,pCodeCtx->width, pCodeCtx->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL);
//輸出文件
FILE *fp_yuv = fopen(output_path, "wb");
//一幀一幀讀取壓縮的視頻數(shù)據(jù)
while (av_read_frame(pFormatCtx, packet) >= 0)
{
//找到視頻流
if (packet->stream_index == video_stream_index)
{
avcodec_decode_video2(pCodeCtx, frame, &got_picture_ptr, packet);
//提取p幀,和i幀
if((frame->pict_type == AV_PICTURE_TYPE_I) || (frame->pict_type == AV_PICTURE_TYPE_P))
{
printf("this is i PICTURE\n");
//正在解碼
if (got_picture_ptr)
{
//frame->yuvFrame,轉(zhuǎn)為指定的YUV420P像素幀
sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0,
frame->height, yuvFrame->data, yuvFrame->linesize);
//計(jì)算視頻數(shù)據(jù)總大小
int y_size = pCodeCtx->width * pCodeCtx->height;
//AVFrame->YUV,由于YUV的比例是4:1:1
fwrite(yuvFrame->data[0], 1, y_size, fp_yuv);
fwrite(yuvFrame->data[1], 1, y_size / 4, fp_yuv);
fwrite(yuvFrame->data[2], 1, y_size / 4, fp_yuv);
}
}
//提取b幀
/*
if(frame->pict_type == AV_PICTURE_TYPE_B)
{
//正在解碼
if (got_picture_ptr)
{
//frame->yuvFrame,轉(zhuǎn)為指定的YUV420P像素幀
sws_scale(sws_ctx, (const uint8_t *const *) frame->data, frame->linesize, 0,
frame->height, yuvFrame->data, yuvFrame->linesize);
//計(jì)算視頻數(shù)據(jù)總大小
int y_size = pCodeCtx->width * pCodeCtx->height;
//AVFrame->YUV,由于YUV的比例是4:1:1
fwrite(yuvFrame->data[0], 1, y_size, fp_yuv);
fwrite(yuvFrame->data[1], 1, y_size / 4, fp_yuv);
fwrite(yuvFrame->data[2], 1, y_size / 4, fp_yuv);
}
}
*/
//釋放packet
av_packet_unref(packet);
}
}
//8、釋放資源
fclose(fp_yuv);
av_frame_free(&frame);
av_frame_free(&yuvFrame);
avcodec_close(pCodeCtx);
av_free(out_buffer);
avformat_free_context(pFormatCtx);
return 0;
}
int main()
{
mp4_to_yuv("/home/file/testvideo.mp4",
"/home/file/testvideo.yuv");
return 0;
}
基于ffmpeg提取視頻中的i幀p幀
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- https://my.oschina.net/ShengTcai/blog/850020 關(guān)于FFMPEG 中I幀...
- 說(shuō)起家里青春期孩子的臭美舉動(dòng),幾個(gè)家長(zhǎng)滔滔不絕 : 校服褲子改窄改短;書(shū)包里帶身漂亮衣服,放學(xué)再換上(包括...
- 【日精進(jìn)打卡第23天】【知~學(xué)習(xí)】《六項(xiàng)精進(jìn)》1遍 共28遍《大學(xué)》1遍 共28遍【經(jīng)典名句分享】不讓未來(lái) 后悔,...
- 一個(gè)詞足以表達(dá)我此刻內(nèi)心的感受。順暢!從開(kāi)始到結(jié)尾,每一個(gè)細(xì)胞都在這種順暢的享受當(dāng)中歡呼雀躍。這就是讓我欣喜的好巧...