diff --git a/ERROR_CODES.md b/ERROR_CODES.md new file mode 100644 index 0000000..f336502 --- /dev/null +++ b/ERROR_CODES.md @@ -0,0 +1,60 @@ +# GDE GoZen error codes + +## Video class + +### get_video_file_meta + +No error code but returns an empty dictionary when nothing was able to be read. + +### open_video + +- 0: OK; +- -1: Couldn't open video file; +- -2: Failed setting up of audio decoder; +- -3: Failed setting up of video decoder; +- -4: Failed setting up of SWS; +- -5: Video file is not usable due to limitations; +- -6: Invalid frame-rate found in video; +- -7: Could not establish the total amount of frames in video files; +- -8: Failed setting up of SWR; +- -9: Audio seeking error; + +### seek_frame and next_frame + +No error code but returns an empty picture when an error occured. + +## Renderer class + +### open + +- 0: OK; +- -1: Renderer not fully ready (some variables aren't set); +- -2: Failed to open video context; +- -3: Failed to setup video encoder; +- -4: failed to setup audio encoder; +- -5: Failed to setup video stream; +- -6: Failed to setup audio stream; +- -7: Couldn't create packet; +- -8: Couldn't create frame; +- -9: Couldn't create SWS; +- -10: Couldn't create SWR; +- -11: Failed to open video file; +- -12: Failed to write stream header; + +### send_frame + +- 0: OK; +- -1: Video codec isn't open; +- -2: Frame is not write-able; +- -3: Couldn't send frame to encoder; + +Any other response is an FFmpeg error code which has to do with sending, receiving, and writing frames. + + +### send_audio + +- 0: OK; +- -1: Audio rendering is not enabled; +- -2: Audio codec isn't open; + +### diff --git a/src/renderer.cpp b/src/renderer.cpp index c53eda5..95f4bc8 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1,7 +1,6 @@ #include "renderer.hpp" #include -// TODO: Set proper return errors and document them! Renderer::~Renderer() { close(); @@ -119,7 +118,7 @@ int Renderer::open() { av_stream_video = avformat_new_stream(av_format_ctx, NULL); if (!av_stream_video) { UtilityFunctions::printerr("Couldn't create stream!"); - return -3; + return -7; } av_codec_ctx_video->codec_id = av_codec_id_video; @@ -137,25 +136,25 @@ int Renderer::open() { av_codec_audio = avcodec_find_encoder(av_codec_id_audio); if (!av_codec_audio) { UtilityFunctions::printerr("Audio codec not found!"); - return -3; + return -4; } av_codec_ctx_audio = avcodec_alloc_context3(av_codec_audio); if (!av_codec_ctx_audio) { UtilityFunctions::printerr("Couldn't allocate audio codec context!"); - return -3; + return -4; } av_packet_audio = av_packet_alloc(); if (!av_packet_audio) { UtilityFunctions::printerr("Couldn't allocate packet!"); - return -3; + return -7; } av_stream_audio = avformat_new_stream(av_format_ctx, NULL); if (!av_stream_audio) { UtilityFunctions::printerr("Couldn't create new stream!"); - return -3; + return -6; } av_codec_ctx_audio->sample_fmt = (*av_codec_audio).sample_fmts ? (*av_codec_audio).sample_fmts[0] : AV_SAMPLE_FMT_FLTP; @@ -179,8 +178,8 @@ int Renderer::open() { } // TODO: Add options in render profile for these type of things - // if (codec->id == AV_CODEC_ID_H264) - // av_opt_set(p_codec_context->priv_data, "preset", "slow", 0); + if (av_codec_video->id == AV_CODEC_ID_H264) + av_opt_set(p_codec_context->priv_data, "preset", "slow", 0); // Opening the video encoder codec response = avcodec_open2(av_codec_ctx_video, av_codec_video, NULL); @@ -201,19 +200,19 @@ int Renderer::open() { av_packet_video = av_packet_alloc(); if (!av_packet_video) { UtilityFunctions::printerr("Couldn't allocate packet!"); - return -3; + return -7; } av_frame_video = av_frame_alloc(); if (!av_frame_video) { UtilityFunctions::printerr("Couldn't allocate frame!"); - return -3; + return -8; } av_frame_video->format = AV_PIX_FMT_YUV420P; av_frame_video->width = resolution.x; av_frame_video->height = resolution.y; if (av_frame_get_buffer(av_frame_video, 0)) { UtilityFunctions::printerr("Couldn't allocate frame data!"); - return -3; + return -8; } sws_ctx = sws_getContext( @@ -222,13 +221,13 @@ int Renderer::open() { SWS_BILINEAR, NULL, NULL, NULL); // TODO: Option to change SWS_BILINEAR if (!sws_ctx) { UtilityFunctions::printerr("Couldn't get sws context!"); - return -7; + return -9; } // Copy video stream params to muxer if (avcodec_parameters_from_context(av_stream_video->codecpar, av_codec_ctx_video) < 0) { UtilityFunctions::printerr("Couldn't copy video stream params!"); - return -3; + return -5; } if (render_audio) { @@ -260,7 +259,7 @@ int Renderer::open() { swr_ctx = swr_alloc(); if (!swr_ctx) { UtilityFunctions::printerr("Couldn't allocate swr!"); - return -4; + return -10; } // Setting audio options @@ -274,7 +273,7 @@ int Renderer::open() { // Initialize resampling context if ((response = swr_init(swr_ctx)) < 0) { UtilityFunctions::printerr("Failed to initialize resampling context!"); - return -4; + return -10; } } @@ -285,7 +284,7 @@ int Renderer::open() { response = avio_open(&av_format_ctx->pb, file_path.utf8(), AVIO_FLAG_WRITE); if (response < 0) { UtilityFunctions::printerr("Couldn't open output file!", get_av_error()); - return -5; + return -11; } } @@ -293,14 +292,13 @@ int Renderer::open() { response = avformat_write_header(av_format_ctx, NULL); if (response < 0) { UtilityFunctions::printerr("Error when writing header!", get_av_error()); - return -6; + return -12; } av_packet_free(&av_packet_video); i = 0; // Reset i for send_frame - return 0; + return OK; } -// TODO: Make argument int frame_nr, this could allow for multi-threaded rendering ... maybe int Renderer::send_frame(Ref a_frame_image) { if (!av_codec_ctx_video) { UtilityFunctions::printerr("Video codec isn't open!"); @@ -323,7 +321,7 @@ int Renderer::send_frame(Ref a_frame_image) { response = avcodec_send_frame(av_codec_ctx_video, av_frame_video); if (response < 0) { UtilityFunctions::printerr("Error sending video frame!", get_av_error()); - return -1; + return -3; } av_packet_video = av_packet_alloc(); @@ -379,12 +377,12 @@ int Renderer::send_audio(Ref a_wav) { // i += av_frame_audio->nb_samples; // while loop end to repeat - return 0; + return OK; } int Renderer::close() { if (av_codec_ctx_video == nullptr) - return 1; + return -1; av_write_trailer(av_format_ctx); @@ -404,5 +402,5 @@ int Renderer::close() { avio_closep(&av_format_ctx->pb); avformat_free_context(av_format_ctx); - return 0; + return OK; } diff --git a/src/video.cpp b/src/video.cpp index 2365073..a9b838b 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -28,36 +28,26 @@ Dictionary Video::get_video_file_meta(String a_file_path) { return l_dic; } -// possible return values: -// 0: OK; -// 1: Couldn't properly open file and collect stream data; -// 2: Codec problems; -// 3: Sws problems; -// 4: Variable framerate (not supported); -// 5: Trouble loading audio; -// 6: Invalid frame-rate; -// 7: Not usable video file; -// int Video::open_video(String a_path, bool a_load_audio) { // Allocate video file context av_format_ctx = avformat_alloc_context(); if (!av_format_ctx) { UtilityFunctions::printerr("Couldn't allocate av format context!"); - return 1; + return -1; } // Open file with avformat if (avformat_open_input(&av_format_ctx, a_path.utf8(), NULL, NULL)) { UtilityFunctions::printerr("Couldn't open video file!"); close_video(); - return 1; + return -1; } // Find stream information if (avformat_find_stream_info(av_format_ctx, NULL)) { UtilityFunctions::printerr("Couldn't find stream info!"); close_video(); - return 1; + return -1; } // Getting the audio and video stream @@ -68,19 +58,18 @@ int Video::open_video(String a_path, bool a_load_audio) { continue; else if (av_codec_params->codec_type == AVMEDIA_TYPE_AUDIO) { av_stream_audio = av_format_ctx->streams[i]; - if (a_load_audio && !_get_audio()) - return 5; + if (a_load_audio && !(response = _get_audio())) + return response; } else if (av_codec_params->codec_type == AVMEDIA_TYPE_VIDEO) av_stream_video = av_format_ctx->streams[i]; } // Setup Decoder codec context - UtilityFunctions::print("Setting up video decoder ..."); const AVCodec *av_codec_video = avcodec_find_decoder(av_stream_video->codecpar->codec_id); if (!av_codec_video) { UtilityFunctions::printerr("Couldn't find any codec decoder for video!"); close_video(); - return 2; + return -3; } // Allocate codec context for decoder @@ -88,21 +77,21 @@ int Video::open_video(String a_path, bool a_load_audio) { if (av_codec_ctx_video == NULL) { UtilityFunctions::printerr("Couldn't allocate codec context for video!"); close_video(); - return 2; + return -3; } // Copying parameters if (avcodec_parameters_to_context(av_codec_ctx_video, av_stream_video->codecpar)) { UtilityFunctions::printerr("Couldn't initialize video codec context!"); close_video(); - return 2; + return -3; } // Open codec - Video if (avcodec_open2(av_codec_ctx_video, av_codec_video, NULL)) { UtilityFunctions::printerr("Couldn't open video codec!"); close_video(); - return 2; + return -3; } // Enable multi-threading for decoding - Video @@ -126,7 +115,7 @@ int Video::open_video(String a_path, bool a_load_audio) { if (!sws_ctx) { UtilityFunctions::printerr("Couldn't get SWS context!"); close_video(); - return 3; + return -4; } // Byte_array setup @@ -142,15 +131,17 @@ int Video::open_video(String a_path, bool a_load_audio) { bool l_duration_from_bitrate = av_format_ctx->duration_estimation_method == AVFMT_DURATION_FROM_BITRATE; if (l_duration_from_bitrate) { UtilityFunctions::printerr("This video file is not usable!"); - return 7; + return -5; } response = av_seek_frame(av_format_ctx, -1, start_time_video, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY); if (response < 0) { print_av_error("Seeking to beginning error: "); + return -5; } _get_frame(av_codec_ctx_video, av_stream_video->index); if (response) { print_av_error("Something went wrong getting first frame!"); + return -5; } // Checking for interlacing and what type of interlacing @@ -161,7 +152,7 @@ int Video::open_video(String a_path, bool a_load_audio) { framerate = av_q2d(av_guess_frame_rate(av_format_ctx, av_stream_video, av_frame)); if (framerate == 0) { UtilityFunctions::printerr("Invalid frame-rate for video found!"); - return 6; + return -6; } // Setting variables @@ -174,8 +165,8 @@ int Video::open_video(String a_path, bool a_load_audio) { if (av_stream_video->r_frame_rate.num == av_stream_video->avg_frame_rate.num) { variable_framerate = false; } else { - UtilityFunctions::print("Variable framerate detected, aborting! (not supported)"); - return 4; + UtilityFunctions::printerr("Variable framerate detected, aborting! (not supported)"); + return -6; } } @@ -187,8 +178,8 @@ int Video::open_video(String a_path, bool a_load_audio) { video_duration = av_format_ctx->duration; if (av_stream_video->duration == AV_NOPTS_VALUE || l_duration_from_bitrate) { if (video_duration == AV_NOPTS_VALUE || l_duration_from_bitrate) { - UtilityFunctions::print("Video file is not usable!"); - return 7; + UtilityFunctions::printerr("Video file is not usable!"); + return -7; } else { AVRational l_temp_rational = AVRational{1, AV_TIME_BASE}; if (l_temp_rational.num != av_stream_video->time_base.num || l_temp_rational.num != av_stream_video->time_base.num) @@ -201,7 +192,6 @@ int Video::open_video(String a_path, bool a_load_audio) { av_packet_free(&av_packet); av_frame_free(&av_frame); - UtilityFunctions::print("Video is open!"); is_open = true; return OK; } @@ -231,16 +221,13 @@ void Video::print_av_error(const char *a_message) { UtilityFunctions::printerr((std::string(a_message) + l_error_buffer).c_str()); } -bool Video::_get_audio() { +int Video::_get_audio() { // Audio Decoder Setup - UtilityFunctions::print("Setting up audio decoder ..."); - - // Setup Decoder codec context const AVCodec *av_codec_audio = avcodec_find_decoder(av_stream_audio->codecpar->codec_id); if (!av_codec_audio) { UtilityFunctions::printerr("Couldn't find any codec decoder for audio!"); close_video(); - return false; + return -2; } // Allocate codec context for decoder @@ -248,21 +235,21 @@ bool Video::_get_audio() { if (av_codec_ctx_audio == NULL) { UtilityFunctions::printerr("Couldn't allocate codec context for audio!"); close_video(); - return false; + return -2; } // Copying parameters if (avcodec_parameters_to_context(av_codec_ctx_audio, av_stream_audio->codecpar)) { UtilityFunctions::printerr("Couldn't initialize audio codec context!"); close_video(); - return false; + return -2; } // Open codec - Audio if (avcodec_open2(av_codec_ctx_audio, av_codec_audio, NULL)) { UtilityFunctions::printerr("Couldn't open audio codec!"); close_video(); - return false; + return -2; } // Enable multi-threading for decoding - Audio @@ -287,29 +274,27 @@ bool Video::_get_audio() { if (response < 0) { print_av_error("Failed to obtain SWR context!"); close_video(); - return false; + return -8; } else if (!swr_ctx) { UtilityFunctions::printerr("Could not allocate re-sampler context!"); close_video(); - return false; + return -8; } response = swr_init(swr_ctx); if (response < 0) { print_av_error("Couldn't initialize SWR!"); close_video(); - return false; + return -8; } - UtilityFunctions::print("Getting audio ..."); - // Set the seeker to the beginning int start_time_audio = av_stream_audio->start_time != AV_NOPTS_VALUE ? av_stream_audio->start_time : 0; avcodec_flush_buffers(av_codec_ctx_audio); response = av_seek_frame(av_format_ctx, -1, start_time_audio, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY); if (response < 0) { UtilityFunctions::printerr("Can't seek to the beginning of audio stream!"); - return false; + return -9; } av_packet = av_packet_alloc(); @@ -378,8 +363,7 @@ bool Video::_get_audio() { av_frame_free(&av_frame); av_packet_free(&av_packet); - UtilityFunctions::print("Audio successfully saved to memory!"); - return true; + return OK; } Ref Video::seek_frame(int a_frame_nr) { @@ -405,7 +389,7 @@ Ref Video::seek_frame(int a_frame_nr) { while (true) { _get_frame(av_codec_ctx_video, av_stream_video->index); if (response) { - UtilityFunctions::print("Problem happened getting frame in seek_frame! ", response); + UtilityFunctions::printerr("Problem happened getting frame in seek_frame! ", response); break; } diff --git a/src/video.hpp b/src/video.hpp index 426168d..4e081d0 100644 --- a/src/video.hpp +++ b/src/video.hpp @@ -69,7 +69,7 @@ class Video : public Resource { Ref next_frame(); inline Ref get_audio() { return audio; }; - bool _get_audio(); + int _get_audio(); inline float get_framerate() { return framerate; }