首页 > 代码库 > 分享一段代码,基于 ffmpeg 的视频转化为图片
分享一段代码,基于 ffmpeg 的视频转化为图片
代码如下:
function Video2Bmp(const strVideoFileName, strSavePath: string): Boolean; var pfc1 : PAVFormatContext; pfc2 : PAVFormatContext; intVideoStreamIndex: Integer; pps : PPAVStream; III : Integer; pcc : PAVCodecContext; pCodec : PAVCodec; pFrameVdo : PAVFrame; pFrameRGB : PAVFrame; psc : PSwsContext; avp : TAVPacket; intRemain : Integer; bFirst : Boolean; intDecoded : Integer; intFrameFinished : Integer; bmp : TBitmap; label lbexit; begin Result := False; { 1. 注册所有容器格式和CODEC } av_register_all(); { 2. 打开文件 } pfc1 := nil; if avformat_open_input(pfc1, PAnsiChar(AnsiString(strVideoFileName)), nil, nil) <> 0 then begin ShowMessage('打开文件失败,请检查你的文件!'); Exit; end; { 3. 从文件中提取流信息 } if avformat_find_stream_info(pfc1, nil) < 0 then begin ShowMessage('不存在任何音频或视频流!'); Exit; end; { 4. 穷举所有的流,查找是否包含视频流 } intVideoStreamIndex := -1; pfc2 := pfc1; pps := pfc1^.streams; for III := 0 to pfc1^.nb_streams - 1 do begin if pps^.codec.codec_type = AVMEDIA_TYPE_VIDEO then begin intVideoStreamIndex := III; end; inc(pps); end; if intVideoStreamIndex = -1 then begin ShowMessage('不存在视频流!'); Exit; end; { 5. 定位到视频流 } inc(pfc1^.streams, intVideoStreamIndex); pcc := pfc1^.streams^.codec; pCodec := avcodec_find_decoder(pcc^.codec_id); if pCodec = nil then begin ShowMessage('找不到视频流!'); Exit; end; { 6. 修正视频流 } if (pCodec^.capabilities and CODEC_CAP_TRUNCATED) = CODEC_CAP_TRUNCATED then pcc^.flags := pcc.flags or CODEC_FLAG_TRUNCATED; if avcodec_open2(pcc, pCodec, nil) < 0 then begin ShowMessage('打开视频流发生错误!'); Exit; end; { 7. 视频流转化为BMP } if (pcc^.time_base.num > 1000) and (pcc^.time_base.den = 1) then pcc^.time_base.den := 1000; pFrameVdo := avcodec_alloc_frame(); pFrameRGB := avcodec_alloc_frame; { 按视频帧的原始大小输出图片 } avpicture_alloc(PAVPicture(pFrameRGB), AV_PIX_FMT_RGB32, pcc^.Width, pcc^.Height); psc := sws_getContext(pcc^.Width, pcc^.Height, pcc^.pix_fmt, pcc^.Width, pcc^.Height, AV_PIX_FMT_RGB32, SWS_BICUBIC, nil, nil, nil); intRemain := 0; bFirst := True; { 查找视频的每一帧 } while True do begin if bFirst then begin bFirst := False; avp.data := nil; end; while True do begin while intRemain > 0 do begin intDecoded := avcodec_decode_video2(pcc, pFrameVdo, intFrameFinished, @avp); if intDecoded < 0 then break; dec(intRemain, intDecoded); { 找到完整的一帧 } if intFrameFinished <> 0 then begin { 按原图输出 } sws_scale(psc, @pFrameVdo^.data, @pFrameVdo^.linesize, 0, pcc^.Height, @pFrameRGB^.data, @pFrameRGB^.linesize); { 输出位图 } bmp := TBitmap.Create; try bmp.PixelFormat := pf32bit; bmp.Width := pcc^.Width; bmp.Height := pcc^.Height; for III := 0 to bmp.Height - 1 do begin CopyMemory(bmp.ScanLine[III], Pointer(Integer(pFrameRGB.data[0]) + bmp.Width * 4 * III), bmp.Width * 4); end; bmp.SaveToFile(Format('%s\%d.bmp', [strSavePath, GetTickCount])); finally bmp.free; end; { 寻找下一帧 } Continue; end; end; repeat if av_read_frame(pfc2, @avp) < 0 then goto lbexit; until avp.stream_index = intVideoStreamIndex; intRemain := avp.size; end; lbexit: avcodec_decode_video2(pcc, pFrameVdo, intFrameFinished, @avp); if avp.data <> nil then av_free_packet(@avp); if intFrameFinished = 0 then break; end; { 8. 释放资源 } sws_freeContext(psc); avpicture_free(PAVPicture(pFrameRGB)); av_free(pFrameRGB); av_free(pFrameVdo); avcodec_close(pcc); avformat_close_input(pfc1); { 9. 返回成功 } Result := True; end;
分享一段代码,基于 ffmpeg 的视频转化为图片
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。