📄 cimgffmpeg.h
字号:
{ videoStream=i; break; } if(videoStream==-1) return -1; // Didn't find a video stream } nb_frames = pFormatCtx->streams[videoStream]->nb_frames; if (nb_frames > 0) { //the easy way if value is already contained in struct av_close_input_file(pFormatCtx); return nb_frames; } else { // frames must be counted AVPacket packet; //read each frame - one frame per packet while(av_read_frame(pFormatCtx, &packet)>=0) { if(packet.stream_index==videoStream) { //packet is from video stream nb_frames++; } av_free_packet(&packet); } // Close the video file av_close_input_file(pFormatCtx); return nb_frames; }}float fps(const char *filename){ AVFormatContext *pFormatCtx; // Open video file if (av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)) return -1 ; // Couldn't open file // Retrieve stream information if(av_find_stream_info(pFormatCtx)<0) return -1; // Couldn't find stream information // Find the first video stream int videoStream=-1; for(unsigned int i=0; i<pFormatCtx->nb_streams; i++) { if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { videoStream=i; break; } if(videoStream==-1) return -1; // Didn't find a video stream } av_close_input_file(pFormatCtx); int num = (pFormatCtx->streams[videoStream]->r_frame_rate).num; int den = (pFormatCtx->streams[videoStream]->r_frame_rate).den; return (num/den);}//! play a list of CImg's given a CImgList. /* * This function is not really meant to function as a video player as much as a simple * debugging tool. It is meant to be run in a thread. The video is played at 1 CImg per second * @param pVideo - a pointer to a CImgList object containing the CImg's to be played */void *PlayVideo(void *info){ video_info_t *pvideo_info = (video_info_t *)info; int fps = pvideo_info->fps; CImgList<unsigned char> *videolist = (CImgList<unsigned char> *)pvideo_info->pList; CImg<> current = videolist->front(); CImgDisplay disp(current,"video"); //display frame every second clock_t interval = (time_t)((1/fps)*(CLOCKS_PER_SEC)); clock_t n = clock(); while (!videolist->is_empty() && !disp.is_closed) { if (videolist->size > 1) { videolist->pop_front(); current = videolist->front(); disp.display(current); while ( n + interval > clock()){}; n = clock(); } else if (videolist->size == 1){ videolist->pop_front(); } else pthread_exit(NULL); } pthread_exit(NULL);}/** * !write a sequence of CImg's to video file. * Purpose: write sequence of images in cimg list at a given framerate * using given filename, use pixel format PIX_FMT_YUV420P * The function expects the images to be either gray scale (dim v = 1) or * rgb images (dim v == 3). Other sizes return -1. * * @param pImlist reference to CImgList * @param filename name of video file to create - with proper extension - e.g. * ".avi, .mpeg, .wmv, etc." * @param fps int value for number of frames per second * @param stream_duration maximum length of video stream (secs) * @return int number of frames recorded to file, < 0 for errors **/template<class T>int WriteFrames(CImgList<T> *pImList,const char *filename, int fps,float stream_duration=100.0){ int width = (pImList->front()).dimx(); int height = (pImList->front()).dimy(); int nb_channels = (pImList->front()).dimv(); if ((nb_channels != 1) && (nb_channels != 3)) throw new CImgIOException("dimv of image not acceptable"); if (!filename) throw new CImgIOException("no file name given"); int frame_count = 0; PixelFormat dest_pxl_fmt = PIX_FMT_YUV420P; PixelFormat src_pxl_fmt = (nb_channels == 3) ? PIX_FMT_RGB24 : PIX_FMT_GRAY8; int sws_flags = SWS_FAST_BILINEAR;//interpolation method (keeping same size images for now) AVOutputFormat *fmt = NULL; fmt = guess_format(NULL,filename,NULL); if (!fmt){ //default format "mpeg" fmt = guess_format("mpeg",NULL,NULL); } if (!fmt){ //unable to retrieve output format throw new CImgIOException("could not determine format from filename"); } AVFormatContext *oc = NULL; oc = av_alloc_format_context(); if (!oc){ //unable to allocate format context throw new CImgIOException("mem allocation error for format context"); } AVCodec *codec = NULL; AVFrame *picture = NULL; AVFrame *tmp_pict = NULL; oc->oformat = fmt; snprintf(oc->filename, sizeof(oc->filename),"%s",filename); av_register_all(); //add video stream int stream_index = 0; AVStream *video_str = NULL; if (fmt->video_codec != CODEC_ID_NONE) { video_str = av_new_stream(oc,stream_index); if (!video_str){ //no stream allocated av_free(oc); throw new CImgIOException("unable to create new video stream"); } } else { //no codec identified av_free(oc); throw new CImgIOException("no codec identified"); } AVCodecContext *c = video_str->codec; c->codec_id = fmt->video_codec; c->codec_type = CODEC_TYPE_VIDEO; c->bit_rate = 400000; c->width = width; c->height = height; c->time_base.num = 1; c->time_base.den = fps; c->gop_size = 12; c->pix_fmt = dest_pxl_fmt; if (c->codec_id == CODEC_ID_MPEG2VIDEO) c->max_b_frames = 2; if (c->codec_id == CODEC_ID_MPEG1VIDEO) c->mb_decision = 2; if (av_set_parameters(oc,NULL) < 0){ //parameters not properly set av_free(oc); throw new CImgIOException("parameters for avcodec not properly set"); } //dump_format(oc,0,filename,1); //open codecs and alloc buffers codec = avcodec_find_encoder(c->codec_id); if (!codec){ //unable to find codec av_free(oc); throw new CImgIOException("no codec found"); } if (avcodec_open(c,codec) < 0) //fail to open codec throw new CImgIOException("unable to open codec"); tmp_pict = avcodec_alloc_frame(); if (!tmp_pict){ //unable to allocate memory for tmp_pict frame avcodec_close(video_str->codec); av_free(oc); throw new CImgIOException("mem alloc error for tmp_pict data buffer"); } tmp_pict->linesize[0] = (src_pxl_fmt == PIX_FMT_RGB24) ? 3*width : width ; tmp_pict->type = FF_BUFFER_TYPE_USER; int tmp_size = avpicture_get_size(src_pxl_fmt,width,height); uint8_t *tmp_buffer = (uint8_t*)av_malloc(tmp_size); if (!tmp_buffer){ //unable to allocate memory for tmp buffer av_free(tmp_pict); avcodec_close(video_str->codec); av_free(oc); throw new CImgIOException("mem alloc error for tmp buffer"); } //associate buffer with tmp_pict avpicture_fill((AVPicture*)tmp_pict,tmp_buffer,src_pxl_fmt,width,height); picture = avcodec_alloc_frame(); if (!picture){ //unable to allocate picture frame av_free(tmp_pict->data[0]); av_free(tmp_pict); avcodec_close(video_str->codec); av_free(oc); throw new CImgIOException("mem alloc error for picture frame"); } int size = avpicture_get_size(c->pix_fmt,width,height); uint8_t *buffer = (uint8_t*)av_malloc(size); if (!buffer){ //unable to allocate buffer av_free(picture); av_free(tmp_pict->data[0]); av_free(tmp_pict); avcodec_close(video_str->codec); av_free(oc); throw new CImgIOException("mem alloc error for picture frame buffer"); } //associate the buffer with picture avpicture_fill((AVPicture*)picture,buffer,c->pix_fmt,width,height); //open file if ( !(fmt->flags & AVFMT_NOFILE) ){ if (url_fopen(&oc->pb,filename,URL_WRONLY) < 0) throw new CImgIOException("unable to open file"); } if (av_write_header(oc) < 0) throw new CImgIOException("could not write header"); double video_pts; SwsContext *img_convert_context = NULL; img_convert_context = sws_getContext(width,height,src_pxl_fmt, c->width,c->height,c->pix_fmt,sws_flags,NULL,NULL,NULL); if (!img_convert_context){ //unable to get swscale context if (!(fmt->flags & AVFMT_NOFILE)) url_fclose(oc->pb); av_free(picture->data); av_free(picture); av_free(tmp_pict->data[0]); av_free(tmp_pict); avcodec_close(video_str->codec); av_free(oc); throw new CImgIOException("unable to get conversion context"); } int ret=0, out_size; uint8_t *video_outbuf = NULL; int video_outbuf_size = 1000000; video_outbuf = (uint8_t*)av_malloc(video_outbuf_size); if (!video_outbuf){ if (!(fmt->flags & AVFMT_NOFILE)) url_fclose(oc->pb); av_free(picture->data); av_free(picture); av_free(tmp_pict->data[0]); av_free(tmp_pict); avcodec_close(video_str->codec); av_free(oc); throw new CImgIOException("mem alloc error"); } //loop through each image in list for (unsigned int i = 0; i < pImList->size; i++) { frame_count++; CImg<uint8_t> currentIm = pImList->at(i); CImg<uint8_t> red,green,blue,gray; if (src_pxl_fmt == PIX_FMT_RGB24){ red = currentIm.get_channel(0); green = currentIm.get_channel(1); blue = currentIm.get_channel(2); cimg_forXY(red,X,Y){ //assign pizel values to data buffer in interlaced RGBRGB ... format tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X] = red(X,Y); tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X + 1] = green(X,Y); tmp_pict->data[0][Y*tmp_pict->linesize[0] + 3*X + 2] = blue(X,Y); } } else { gray = currentIm.get_channel(0); cimg_forXY(gray,X,Y){ tmp_pict->data[0][Y*tmp_pict->linesize[0] + X] = gray(X,Y); } } if (video_str) video_pts = (video_str->pts.val * video_str->time_base.num)/(video_str->time_base.den); else video_pts = 0.0; if ((!video_str) || (video_pts >= stream_duration)) break; if (sws_scale(img_convert_context,tmp_pict->data,tmp_pict->linesize,0,c->height,picture->data,picture->linesize) < 0){ break;;//break out of loop } out_size = avcodec_encode_video(c,video_outbuf,video_outbuf_size,picture); if (out_size > 0){ AVPacket pkt; av_init_packet(&pkt); pkt.pts = av_rescale_q(c->coded_frame->pts,c->time_base,video_str->time_base); if (c->coded_frame->key_frame){ pkt.flags |= PKT_FLAG_KEY; } pkt.stream_index = video_str->index; pkt.data = video_outbuf; pkt.size = out_size; ret = av_write_frame(oc,&pkt); } else if (out_size < 0){ break;//failure occured in avcodec_encode_video() } if (ret != 0){ //error occured in writing frame break; } } //close codec if (video_str){ avcodec_close(video_str->codec); av_free(picture->data[0]); av_free(picture); av_free(tmp_pict->data[0]); av_free(tmp_pict); } if (av_write_trailer(oc) < 0) throw new CImgIOException("could not write trailer"); av_freep(&oc->streams[stream_index]->codec); av_freep(&oc->streams[stream_index]); if (!(fmt->flags & AVFMT_NOFILE)){ if (url_fclose(oc->pb) < 0) throw new CImgIOException("could not close file"); } av_free(oc); av_free(video_outbuf); return frame_count;}#endif /*CIMGFFMPEG_H_*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -