|
@@ -0,0 +1,140 @@
|
|
|
|
+#include <stdio.h>
|
|
|
|
+
|
|
|
|
+extern "C" {
|
|
|
|
+ #include <libavcodec/avcodec.h>
|
|
|
|
+ #include <libavformat/avformat.h>
|
|
|
|
+ #include <libswscale/swscale.h>
|
|
|
|
+ #include <inttypes.h>
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool load_frame(const char* filename, int* width, int* height, unsigned char** data)
|
|
|
|
+{
|
|
|
|
+
|
|
|
|
+ AVFormatContext* av_format_context = avformat_alloc_context();
|
|
|
|
+ if (!av_format_context) {
|
|
|
|
+ fprintf(stderr, "could not allocate AVFormatContext.\n");
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ if (avformat_open_input(&av_format_context, filename, NULL, NULL) ){
|
|
|
|
+ fprintf(stderr, "could not open video file. %s\n", filename);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int video_stream_index = -1;
|
|
|
|
+ bool found = false;
|
|
|
|
+ AVCodec *av_codec;
|
|
|
|
+ AVCodecParameters *av_codec_params;
|
|
|
|
+ for (int i=0; i < av_format_context->nb_streams; ++i) {
|
|
|
|
+ auto stream = av_format_context->streams[i];
|
|
|
|
+ av_codec_params = av_format_context->streams[i]->codecpar;
|
|
|
|
+ av_codec = avcodec_find_decoder(av_codec_params->codec_id);
|
|
|
|
+
|
|
|
|
+ printf("Looking at stream: %d.\n", i);
|
|
|
|
+ if (av_codec_params->codec_type == AVMEDIA_TYPE_VIDEO) {
|
|
|
|
+ printf("Found video stream\n");
|
|
|
|
+ video_stream_index = i;
|
|
|
|
+ found = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (found) {
|
|
|
|
+ video_stream_index = i;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!found) {
|
|
|
|
+ fprintf(stderr, "could not found video stream.\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ AVCodecContext *av_codec_context = avcodec_alloc_context3(av_codec);
|
|
|
|
+ if (!av_codec_context) {
|
|
|
|
+ fprintf(stderr, "could not allocate avcodec context.\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(avcodec_parameters_to_context(av_codec_context, av_codec_params) < 0) {
|
|
|
|
+ fprintf(stderr, "could not initialize AVCodecContext.\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (avcodec_open2(av_codec_context, av_codec, NULL) < 0) {
|
|
|
|
+ fprintf(stderr, "could not open codec.\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ AVFrame *av_frame = av_frame_alloc();
|
|
|
|
+ if (!av_frame) {
|
|
|
|
+ fprintf(stderr, "could not allocate av frame.\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ AVPacket *av_packet = av_packet_alloc();
|
|
|
|
+ if (!av_packet) {
|
|
|
|
+ fprintf(stderr, "could not allocate av packet.\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ int response = -1;
|
|
|
|
+ while (av_read_frame(av_format_context, av_packet) >= 0) {
|
|
|
|
+ if(av_packet->stream_index != video_stream_index){
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ response = avcodec_send_packet(av_codec_context, av_packet);
|
|
|
|
+ if (response < 0) {
|
|
|
|
+ fprintf(stderr, "failed to decode packet [1].\n");
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ response = avcodec_receive_frame(av_codec_context, av_frame);
|
|
|
|
+ if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
|
|
|
|
+ continue;
|
|
|
|
+ } else if (response < 0) {
|
|
|
|
+ //fprintf(stderr, "failed to decode packet: %s\n.", av_err2str(response));
|
|
|
|
+ fprintf(stderr, "failed to decode packet [2].\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ av_packet_unref(av_packet);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ uint8_t *data_in = new uint8_t[av_frame->width * av_frame->height * 4];
|
|
|
|
+
|
|
|
|
+ SwsContext *sws_scaler_ctx = sws_getContext(av_frame->width,
|
|
|
|
+ av_frame->height,
|
|
|
|
+ av_codec_context->pix_fmt,
|
|
|
|
+ av_frame->width,
|
|
|
|
+ av_frame->height,
|
|
|
|
+ AV_PIX_FMT_RGB0,
|
|
|
|
+ SWS_BILINEAR,
|
|
|
|
+ NULL,
|
|
|
|
+ NULL,
|
|
|
|
+ NULL);
|
|
|
|
+
|
|
|
|
+ if (!sws_scaler_ctx) {
|
|
|
|
+ fprintf(stderr, "could not initialize sw scaler context.\n");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ uint8_t* dest[4] = {data_in, NULL, NULL, NULL};
|
|
|
|
+ int dest_linesize[4] = {av_frame->width * 4, 0, 0, 0};
|
|
|
|
+ sws_scale(sws_scaler_ctx, av_frame->data, av_frame->linesize, 0, av_frame->height, dest, dest_linesize);
|
|
|
|
+ sws_freeContext(sws_scaler_ctx);
|
|
|
|
+
|
|
|
|
+ *width = av_frame->width;
|
|
|
|
+ *height = av_frame->height;
|
|
|
|
+
|
|
|
|
+ *data = data_in;
|
|
|
|
+
|
|
|
|
+ avformat_close_input(&av_format_context);
|
|
|
|
+ avformat_free_context(av_format_context);
|
|
|
|
+ av_frame_free(&av_frame);
|
|
|
|
+ av_packet_free(&av_packet);
|
|
|
|
+ avcodec_free_context(&av_codec_context);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+}
|