Skip to content

Commit e990901

Browse files
authored
Add AviUtl2 input plugin (#126)
* Add AviUtl2 input plugin * Use 16-bit PCM output for AviUtl2 audio * Add AviUtl2 multi-track stream selection * Preserve AviUtl2 track options on rebuild failure * Release unused AviUtl2 reader handlers on close * Match libavsmash decoder streams by track id * Avoid lwlibav fallback after libavsmash stream selection * Probe AviUtl2 MP4 tracks in l-smash order * Reject invalid libavsmash track numbers Implemented #119
1 parent b6f3b72 commit e990901

19 files changed

Lines changed: 2171 additions & 14 deletions
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include "au2/ReaderOptions.hpp"
4+
5+
#include "../../common/audio_output.h"
6+
7+
#include <windows.h>
8+
9+
extern "C" {
10+
#include <libavcodec/avcodec.h>
11+
}
12+
13+
namespace au2 {
14+
15+
int setup_audio_rendering(lw_audio_output_handler_t* aohp, AVCodecContext* ctx, AudioOptions* opt, WAVEFORMATEX* format);
16+
17+
} // namespace au2
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
#ifndef NOMINMAX
4+
#define NOMINMAX
5+
#endif
6+
7+
#include <windows.h>
8+
#include <mmsystem.h>
9+
10+
#include "input2.h"
11+
12+
namespace au2 {
13+
14+
bool initialize_plugin(DWORD version) noexcept;
15+
void uninitialize_plugin() noexcept;
16+
INPUT_PLUGIN_TABLE* input_plugin_table() noexcept;
17+
18+
} // namespace au2
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#pragma once
2+
3+
#include "au2/ReaderBackend.hpp"
4+
#include "input2.h"
5+
6+
#include <memory>
7+
#include <string>
8+
#include <vector>
9+
10+
namespace au2 {
11+
12+
struct InputTrackList {
13+
struct Track {
14+
int stream_index = -1;
15+
int media_track_index = -1;
16+
};
17+
std::vector<Track> video;
18+
std::vector<Track> audio;
19+
};
20+
21+
class InputSession {
22+
public:
23+
static std::unique_ptr<InputSession> open(LPCWSTR path);
24+
25+
~InputSession();
26+
27+
InputSession(const InputSession&) = delete;
28+
InputSession& operator=(const InputSession&) = delete;
29+
30+
bool info(INPUT_INFO& out) const noexcept;
31+
int read_video(int frame, void* dst) noexcept;
32+
int read_audio(int start, int length, void* dst) noexcept;
33+
bool is_keyframe(int frame) noexcept;
34+
int set_track(int type, int index) noexcept;
35+
36+
private:
37+
InputSession(std::string path, ReaderOptions options, InputTrackList tracks) noexcept;
38+
39+
bool rebuild_core() noexcept;
40+
int track_count(int type) const noexcept;
41+
42+
std::string path_;
43+
ReaderOptions options_ {};
44+
InputTrackList tracks_;
45+
SessionCore core_ {};
46+
int audio_delay_ = 0;
47+
};
48+
49+
} // namespace au2

AviUtl2/include/au2/Path.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <string_view>
5+
6+
namespace au2 {
7+
8+
std::string wide_to_utf8(std::wstring_view text);
9+
bool has_script_extension(std::wstring_view path);
10+
11+
} // namespace au2
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#pragma once
2+
3+
#include "au2/ReaderOptions.hpp"
4+
5+
#include <windows.h>
6+
#include <mmreg.h>
7+
8+
namespace au2 {
9+
10+
struct SessionCore;
11+
12+
struct ReaderCallbacks {
13+
ReaderType type = ReaderType::None;
14+
void* (*open_file)(char* file_name, ReaderOptions* opt) = nullptr;
15+
int (*get_video_track)(SessionCore* session, VideoOptions* opt) = nullptr;
16+
int (*get_audio_track)(SessionCore* session, AudioOptions* opt) = nullptr;
17+
void (*destroy_disposable)(void* private_stuff) = nullptr;
18+
int (*read_video)(SessionCore* session, int sample_number, void* buf) = nullptr;
19+
int (*read_audio)(SessionCore* session, int start, int wanted_length, void* buf) = nullptr;
20+
int (*is_keyframe)(SessionCore* session, int sample_number) = nullptr;
21+
int (*delay_audio)(SessionCore* session, int* start, int wanted_length, int audio_delay) = nullptr;
22+
void (*video_cleanup)(SessionCore* session) = nullptr;
23+
void (*audio_cleanup)(SessionCore* session) = nullptr;
24+
void (*close_file)(void* private_stuff) = nullptr;
25+
};
26+
27+
struct SessionCore {
28+
void* global_private = nullptr;
29+
void (*close_file)(void* private_stuff) = nullptr;
30+
31+
ReaderType video_reader = ReaderType::None;
32+
void* video_private = nullptr;
33+
BITMAPINFOHEADER video_format {};
34+
int framerate_num = 0;
35+
int framerate_den = 1;
36+
uint32_t video_sample_count = 0;
37+
int (*read_video)(SessionCore* session, int sample_number, void* buf) = nullptr;
38+
int (*is_keyframe)(SessionCore* session, int sample_number) = nullptr;
39+
void (*video_cleanup)(SessionCore* session) = nullptr;
40+
void (*close_video_file)(void* private_stuff) = nullptr;
41+
42+
ReaderType audio_reader = ReaderType::None;
43+
void* audio_private = nullptr;
44+
WAVEFORMATEXTENSIBLE audio_format {};
45+
uint32_t audio_pcm_sample_count = 0;
46+
int (*read_audio)(SessionCore* session, int start, int wanted_length, void* buf) = nullptr;
47+
int (*delay_audio)(SessionCore* session, int* start, int wanted_length, int audio_delay) = nullptr;
48+
void (*audio_cleanup)(SessionCore* session) = nullptr;
49+
void (*close_audio_file)(void* private_stuff) = nullptr;
50+
};
51+
52+
const ReaderCallbacks& libavsmash_reader() noexcept;
53+
const ReaderCallbacks& lwlibav_reader() noexcept;
54+
55+
void au2_log_noop(lw_log_handler_t* lhp, lw_log_level level, const char* message);
56+
57+
} // namespace au2
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <windows.h>
5+
#include <mmreg.h>
6+
7+
#include "../../common/utils.h"
8+
9+
#define AU2_MAKE_PITCH(bits) ((((bits) + 31) & ~31) >> 3)
10+
#define AU2_PREFERRED_DECODER_NAMES_BUFSIZE 512
11+
12+
namespace au2 {
13+
14+
enum class ReaderType {
15+
None = 0,
16+
Libavsmash = 1,
17+
Lwlibav = 2,
18+
};
19+
20+
enum class OutputColorspace {
21+
Auto = 0,
22+
Yuy2 = 0,
23+
Rgb24 = 1,
24+
Rgba = 2,
25+
Yc48 = 3,
26+
Lw48 = 4,
27+
};
28+
29+
struct VideoOptions {
30+
int seek_mode = 0;
31+
int forward_seek_threshold = 10;
32+
int scaler = 0;
33+
int apply_repeat_flag = 1;
34+
int field_dominance = 0;
35+
struct {
36+
int active = 0;
37+
int framerate_num = 60000;
38+
int framerate_den = 1001;
39+
} vfr2cfr;
40+
OutputColorspace colorspace = OutputColorspace::Auto;
41+
};
42+
43+
enum {
44+
MIX_LEVEL_INDEX_CENTER = 0,
45+
MIX_LEVEL_INDEX_SURROUND,
46+
MIX_LEVEL_INDEX_LFE,
47+
};
48+
49+
struct AudioOptions {
50+
uint64_t channel_layout = 0;
51+
int sample_rate = 0;
52+
int mix_level[3] = { 71, 71, 0 };
53+
};
54+
55+
struct ReaderOptions {
56+
int threads = 0;
57+
int av_sync = 1;
58+
char preferred_decoder_names_buf[AU2_PREFERRED_DECODER_NAMES_BUFSIZE] {};
59+
const char** preferred_decoder_names = nullptr;
60+
int no_create_index = 0;
61+
int force_video = 0;
62+
int force_video_index = -1;
63+
int force_audio = 0;
64+
int force_audio_index = -1;
65+
int libavsmash_video_media_index = 0;
66+
int libavsmash_audio_media_index = 0;
67+
VideoOptions video;
68+
AudioOptions audio;
69+
};
70+
71+
} // namespace au2
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include "au2/ReaderOptions.hpp"
4+
5+
#include "../../common/video_output.h"
6+
7+
#include <windows.h>
8+
9+
extern "C" {
10+
#include <libavutil/frame.h>
11+
}
12+
13+
namespace au2 {
14+
15+
typedef void FuncConvertColorspace(lw_video_output_handler_t* vohp, AVFrame* picture, void* buf);
16+
typedef int FuncConvertColorspaceResult(lw_video_output_handler_t* vohp, AVFrame* picture, uint8_t* buf);
17+
18+
struct VideoOutputHandler {
19+
int output_linesize = 0;
20+
uint32_t output_frame_size = 0;
21+
uint8_t* back_ground = nullptr;
22+
uint8_t* another_chroma = nullptr;
23+
uint32_t another_chroma_size = 0;
24+
AVFrame* yuv444p16 = nullptr;
25+
int (*convert_colorspace)(lw_video_output_handler_t* vohp, AVFrame* picture, uint8_t* buf) = nullptr;
26+
};
27+
28+
int setup_video_rendering(lw_video_output_handler_t* vohp, VideoOptions* opt, BITMAPINFOHEADER* format, int output_width,
29+
int output_height, enum AVPixelFormat input_pixel_format);
30+
31+
int convert_colorspace(lw_video_output_handler_t* vohp, AVFrame* picture, uint8_t* buf);
32+
33+
} // namespace au2

AviUtl2/include/au2/input2.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <windows.h>
4+
#include <mmsystem.h>
5+
6+
struct INPUT_INFO {
7+
int flag;
8+
static constexpr int FLAG_VIDEO = 1;
9+
static constexpr int FLAG_AUDIO = 2;
10+
static constexpr int FLAG_TIME_TO_FRAME = 16;
11+
int rate;
12+
int scale;
13+
int n;
14+
BITMAPINFOHEADER* format;
15+
int format_size;
16+
int audio_n;
17+
WAVEFORMATEX* audio_format;
18+
int audio_format_size;
19+
};
20+
21+
typedef void* INPUT_HANDLE;
22+
23+
struct INPUT_PLUGIN_TABLE {
24+
int flag;
25+
static constexpr int FLAG_VIDEO = 1;
26+
static constexpr int FLAG_AUDIO = 2;
27+
static constexpr int FLAG_CONCURRENT = 16;
28+
static constexpr int FLAG_MULTI_TRACK = 32;
29+
LPCWSTR name;
30+
LPCWSTR filefilter;
31+
LPCWSTR information;
32+
INPUT_HANDLE (*func_open)(LPCWSTR file);
33+
bool (*func_close)(INPUT_HANDLE ih);
34+
bool (*func_info_get)(INPUT_HANDLE ih, INPUT_INFO* iip);
35+
int (*func_read_video)(INPUT_HANDLE ih, int frame, void* buf);
36+
int (*func_read_audio)(INPUT_HANDLE ih, int start, int length, void* buf);
37+
bool (*func_config)(HWND hwnd, HINSTANCE dll_hinst);
38+
int (*func_set_track)(INPUT_HANDLE ih, int type, int index);
39+
static constexpr int TRACK_TYPE_VIDEO = 0;
40+
static constexpr int TRACK_TYPE_AUDIO = 1;
41+
int (*func_time_to_frame)(INPUT_HANDLE ih, double time);
42+
};

0 commit comments

Comments
 (0)