📄 ffmpeg.c
字号:
ffmpeg->video_outbuf = NULL; if (!(ffmpeg->oc->oformat->flags & AVFMT_RAWPICTURE)) { /* allocate output buffer */ /* XXX: API change will be done */ ffmpeg->video_outbuf_size = 200000; ffmpeg->video_outbuf = mymalloc(ffmpeg->video_outbuf_size); } /* allocate the encoded raw picture */ ffmpeg->picture = avcodec_alloc_frame(); if (!ffmpeg->picture) { motion_log(LOG_ERR, 1, "avcodec_alloc_frame - could not alloc frame"); ffmpeg_cleanups(ffmpeg); return (NULL); } /* set variable bitrate if requested */ if (ffmpeg->vbr) { ffmpeg->picture->quality = ffmpeg->vbr; } /* set the frame data */ ffmpeg->picture->data[0] = y; ffmpeg->picture->data[1] = u; ffmpeg->picture->data[2] = v; ffmpeg->picture->linesize[0] = ffmpeg->c->width; ffmpeg->picture->linesize[1] = ffmpeg->c->width / 2; ffmpeg->picture->linesize[2] = ffmpeg->c->width / 2; /* open the output file, if needed */ if (!(ffmpeg->oc->oformat->flags & AVFMT_NOFILE)) { char file_proto[256]; /* Use append file protocol for mpeg1, to get the append behavior from * url_fopen, but no protocol (=> default) for other codecs. */ if(is_mpeg1) { snprintf(file_proto, sizeof(file_proto), APPEND_PROTO ":%s", filename); } else { snprintf(file_proto, sizeof(file_proto), "%s", filename); } if (url_fopen(&ffmpeg->oc->pb, file_proto, URL_WRONLY) < 0) { /* path did not exist? */ if (errno == ENOENT) { /* create path for file (don't use file_proto)... */ if (create_path(filename) == -1) { ffmpeg_cleanups(ffmpeg); return (NULL); } /* and retry opening the file (use file_proto) */ if (url_fopen(&ffmpeg->oc->pb, file_proto, URL_WRONLY) < 0) { motion_log(LOG_ERR, 1, "url_fopen - error opening file %s",filename); ffmpeg_cleanups(ffmpeg); return (NULL); } /* Permission denied */ } else if (errno == EACCES) { motion_log(LOG_ERR, 1, "url_fopen - error opening file %s" " ... check access rights to target directory", filename); /* create path for file... */ ffmpeg_cleanups(ffmpeg); return (NULL); } else { motion_log(LOG_ERR, 1, "Error opening file %s", filename); ffmpeg_cleanups(ffmpeg); return (NULL); } } } /* write the stream header, if any */ av_write_header(ffmpeg->oc); return ffmpeg;}/* Clean up ffmpeg struct if something was wrong*/void ffmpeg_cleanups(struct ffmpeg *ffmpeg){ int i; /* close each codec */ if (ffmpeg->video_st) { pthread_mutex_lock(&global_lock); avcodec_close(AVSTREAM_CODEC_PTR(ffmpeg->video_st)); pthread_mutex_unlock(&global_lock); av_freep(&ffmpeg->picture); av_freep(&ffmpeg->video_outbuf); } /* free the streams */ for (i = 0; i < ffmpeg->oc->nb_streams; i++) { av_freep(&ffmpeg->oc->streams[i]); }/* if (!(ffmpeg->oc->oformat->flags & AVFMT_NOFILE)) { // close the output file if (ffmpeg->oc->pb) url_fclose(&ffmpeg->oc->pb); }*/ /* free the stream */ av_free(ffmpeg->oc);#if LIBAVFORMAT_BUILD >= 4629 free(ffmpeg->c);#endif free(ffmpeg);}/* Closes a video file. */void ffmpeg_close(struct ffmpeg *ffmpeg){ int i; /* close each codec */ if (ffmpeg->video_st) { pthread_mutex_lock(&global_lock); avcodec_close(AVSTREAM_CODEC_PTR(ffmpeg->video_st)); pthread_mutex_unlock(&global_lock); av_freep(&ffmpeg->picture); av_freep(&ffmpeg->video_outbuf); } /* write the trailer, if any */ av_write_trailer(ffmpeg->oc); /* free the streams */ for (i = 0; i < ffmpeg->oc->nb_streams; i++) { av_freep(&ffmpeg->oc->streams[i]); } if (!(ffmpeg->oc->oformat->flags & AVFMT_NOFILE)) { /* close the output file */ url_fclose(&ffmpeg->oc->pb); } /* free the stream */ av_free(ffmpeg->oc);#if LIBAVFORMAT_BUILD >= 4629 free(ffmpeg->c);#endif free(ffmpeg);}/* Puts the image pointed to by ffmpeg->picture. */void ffmpeg_put_image(struct ffmpeg *ffmpeg) { ffmpeg_put_frame(ffmpeg, ffmpeg->picture);}/* Puts an arbitrary picture defined by y, u and v. */void ffmpeg_put_other_image(struct ffmpeg *ffmpeg, unsigned char *y, unsigned char *u, unsigned char *v){ AVFrame *picture; /* allocate the encoded raw picture */ picture = ffmpeg_prepare_frame(ffmpeg, y, u, v); if (picture) { ffmpeg_put_frame(ffmpeg, picture); free(picture); }}/* Encodes and writes a video frame using the av_write_frame API. This is * a helper function for ffmpeg_put_image and ffmpeg_put_other_image. */void ffmpeg_put_frame(struct ffmpeg *ffmpeg, AVFrame *pic){ int out_size, ret;#ifdef FFMPEG_AVWRITEFRAME_NEWAPI AVPacket pkt; av_init_packet(&pkt); /* init static structure */ pkt.stream_index = ffmpeg->video_st->index;#endif /* FFMPEG_AVWRITEFRAME_NEWAPI */ if (ffmpeg->oc->oformat->flags & AVFMT_RAWPICTURE) { /* raw video case. The API will change slightly in the near future for that */#ifdef FFMPEG_AVWRITEFRAME_NEWAPI pkt.flags |= PKT_FLAG_KEY; pkt.data = (uint8_t *)pic; pkt.size = sizeof(AVPicture); ret = av_write_frame(ffmpeg->oc, &pkt);#else ret = av_write_frame(ffmpeg->oc, ffmpeg->video_st->index, (uint8_t *)pic, sizeof(AVPicture));#endif /* FFMPEG_AVWRITEFRAME_NEWAPI */ } else { /* encode the image */ out_size = avcodec_encode_video(AVSTREAM_CODEC_PTR(ffmpeg->video_st), ffmpeg->video_outbuf, ffmpeg->video_outbuf_size, pic); /* if zero size, it means the image was buffered */ if (out_size != 0) { /* write the compressed frame in the media file */ /* XXX: in case of B frames, the pts is not yet valid */#ifdef FFMPEG_AVWRITEFRAME_NEWAPI pkt.pts = AVSTREAM_CODEC_PTR(ffmpeg->video_st)->coded_frame->pts; if (AVSTREAM_CODEC_PTR(ffmpeg->video_st)->coded_frame->key_frame) { pkt.flags |= PKT_FLAG_KEY; } pkt.data = ffmpeg->video_outbuf; pkt.size = out_size; ret = av_write_frame(ffmpeg->oc, &pkt);#else ret = av_write_frame(ffmpeg->oc, ffmpeg->video_st->index, ffmpeg->video_outbuf, out_size);#endif /* FFMPEG_AVWRITEFRAME_NEWAPI */ } else { ret = 0; } } if (ret != 0) { motion_log(LOG_ERR, 1, "Error while writing video frame"); return; }}/* Allocates and prepares a picture frame by setting up the U, Y and V pointers in * the frame according to the passed pointers. * * Returns NULL If the allocation fails. * * The returned AVFrame pointer must be freed after use. */AVFrame *ffmpeg_prepare_frame(struct ffmpeg *ffmpeg, unsigned char *y, unsigned char *u, unsigned char *v){ AVFrame *picture; picture = avcodec_alloc_frame(); if (!picture) { motion_log(LOG_ERR, 1, "Could not alloc frame"); return NULL; } /* take care of variable bitrate setting */ if (ffmpeg->vbr) { picture->quality = ffmpeg->vbr; } /* setup pointers and line widths */ picture->data[0] = y; picture->data[1] = u; picture->data[2] = v; picture->linesize[0] = ffmpeg->c->width; picture->linesize[1] = ffmpeg->c->width / 2; picture->linesize[2] = ffmpeg->c->width / 2; return picture;}/** ffmpeg_deinterlace * Make the image suitable for deinterlacing using ffmpeg, then deinterlace the picture. * * Parameters * img image in YUV420P format * width image width in pixels * height image height in pixels * * Returns * Function returns nothing. * img contains deinterlaced image */void ffmpeg_deinterlace(unsigned char *img, int width, int height){ AVFrame *picture; int width2 = width / 2; picture = avcodec_alloc_frame(); if (!picture) { motion_log(LOG_ERR, 1, "Could not alloc frame"); return; } picture->data[0] = img; picture->data[1] = img+width*height; picture->data[2] = picture->data[1]+(width*height)/4; picture->linesize[0] = width; picture->linesize[1] = width2; picture->linesize[2] = width2; /* We assume using 'PIX_FMT_YUV420P' always */ avpicture_deinterlace((AVPicture *)picture, (AVPicture *)picture, PIX_FMT_YUV420P, width, height); av_free(picture); return;}/** ffmpeg_avcodec_log * Handle any logging output from the ffmpeg library avcodec. * * Parameters * *ignoreme A pointer we will ignore * errno_flag The error number value * fmt Text message to be used for log entry in printf() format. * ap List of variables to be used in formatted message text. * * Returns * Function returns nothing. */void ffmpeg_avcodec_log(void *ignoreme ATTRIBUTE_UNUSED, int errno_flag, const char *fmt, ...){ char buf[1024]; va_list ap; /* Do not log the message coming from avcodec if the debug_level is not set. */ if (debug_level) { /* Get the message from the argument list passed in */ va_start(ap, fmt); /* Flatten the message coming in from avcodec */ vsnprintf(buf, sizeof(buf), fmt, ap); /* If the debug_level is correct then send the message to the motion logging routine. */ motion_log(LOG_ERR, 0, "ffmpeg_avcodec_log: %s - flag %d", buf, errno_flag); /* Clean up the argument list routine */ va_end(ap); }}#endif /* HAVE_FFMPEG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -