diff options
Diffstat (limited to 'ffmpeg/test.cc')
| -rw-r--r-- | ffmpeg/test.cc | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/ffmpeg/test.cc b/ffmpeg/test.cc new file mode 100644 index 000000000..52b32dd9a --- /dev/null +++ b/ffmpeg/test.cc @@ -0,0 +1,136 @@ +extern "C" { +#include <libavcodec/avcodec.h> +#include <libavformat/avformat.h> +#include <libswscale/swscale.h> +} + +char const video[] = "/home/carl/Films/A town called panic.divx";//Ghostbusters.avi"; + +static void +save_frame (AVFrame *frame, int width, int height, int N) +{ + char filename[32]; + + sprintf (filename, "frame%d.ppm", N); + FILE* file = fopen (filename, "wb"); + if (file == NULL) { + return; + } + + fprintf (file, "P6\n%d %d\n255\n", width, height); + + for (int y = 0; y < height; y++) { + fwrite (frame->data[0] + y * frame->linesize[0], 1, width * 3, file); + } + + fclose (file); +} + +int +main (int argc, char* argv[]) +{ + av_register_all (); + + AVFormatContext* format_context = NULL; + if (avformat_open_input (&format_context, video, NULL, NULL) != 0) { + fprintf (stderr, "avformat_open_input failed.\n"); + return -1; + } + + if (avformat_find_stream_info (format_context, NULL) < 0) { + fprintf (stderr, "av_find_stream_info failed.\n"); + return -1; + } + + av_dump_format (format_context, 0, video, 0); + + int video_stream = -1; + for (uint32_t i = 0; i < format_context->nb_streams; ++i) { + if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + video_stream = i; + break; + } + } + + AVCodecContext* codec_context = format_context->streams[video_stream]->codec; + + AVCodec* codec = avcodec_find_decoder (codec_context->codec_id); + if (codec == NULL) { + fprintf (stderr, "avcodec_find_decoder failed.\n"); + return -1; + } + + if (avcodec_open2 (codec_context, codec, NULL) < 0) { + fprintf (stderr, "avcodec_open failed.\n"); + return -1; + } + + if (codec_context->time_base.num > 1000 && codec_context->time_base.den == 1) { + codec_context->time_base.den = 1000; + } + + AVFrame* frame = avcodec_alloc_frame (); + + AVFrame* frame_RGB = avcodec_alloc_frame (); + if (frame_RGB == NULL) { + fprintf (stderr, "avcodec_alloc_frame failed.\n"); + return -1; + } + + int num_bytes = avpicture_get_size (PIX_FMT_RGB24, codec_context->width, codec_context->height); + uint8_t* buffer = (uint8_t *) malloc (num_bytes); + + avpicture_fill ((AVPicture *) frame_RGB, buffer, PIX_FMT_RGB24, codec_context->width, codec_context->height); + + int i = 0; + AVPacket packet; + while (av_read_frame (format_context, &packet) >= 0) { + + int frame_finished; + + if (packet.stream_index == video_stream) { + avcodec_decode_video2 (codec_context, frame, &frame_finished, &packet); + + if (frame_finished) { + static struct SwsContext *img_convert_context; + + if (img_convert_context == NULL) { + int w = codec_context->width; + int h = codec_context->height; + + img_convert_context = sws_getContext ( + w, h, + codec_context->pix_fmt, + w, h, PIX_FMT_RGB24, SWS_BICUBIC, + NULL, NULL, NULL + ); + + if (img_convert_context == NULL) { + fprintf (stderr, "sws_getContext failed.\n"); + return -1; + } + } + + sws_scale ( + img_convert_context, frame->data, frame->linesize, 0, + codec_context->height, frame_RGB->data, frame_RGB->linesize + ); + + ++i; + if (i > 100 && i < 150) { + save_frame (frame_RGB, codec_context->width, codec_context->height, i); + } + } + } + + av_free_packet (&packet); + } + + free (buffer); + av_free (frame_RGB); + av_free (frame); + avcodec_close(codec_context); + avformat_close_input (&format_context); + + return 0; +} |
