├── .gitignore ├── .gitmodules ├── audioFrame.go ├── build └── .gitkeep ├── callback.go ├── cppsrc ├── decoder.cpp ├── decoder.hpp ├── decoder │ ├── avcodec.cpp │ ├── avcodec.hpp │ ├── jpeg.cpp │ ├── jpeg.hpp │ ├── openh264.cpp │ ├── openh264.hpp │ ├── opus.cpp │ ├── opus.hpp │ ├── png.cpp │ ├── png.hpp │ ├── speex.cpp │ ├── speex.hpp │ ├── theora.cpp │ ├── theora.hpp │ ├── vorbis.cpp │ └── vorbis.hpp ├── encoder.cpp ├── encoder.hpp ├── encoder │ ├── fdkaac.cpp │ ├── fdkaac.hpp │ ├── jpeg.cpp │ ├── jpeg.hpp │ ├── openh264.cpp │ ├── openh264.hpp │ ├── opus.cpp │ ├── opus.hpp │ ├── speex.cpp │ ├── speex.hpp │ ├── theora.cpp │ ├── theora.hpp │ ├── vorbis.cpp │ ├── vorbis.hpp │ ├── x264.cpp │ ├── x264.hpp │ ├── x265.cpp │ └── x265.hpp ├── frame.cpp ├── frame.hpp ├── reader.cpp ├── resampler.cpp ├── resampler.hpp ├── resampler │ ├── audio.cpp │ ├── audio.hpp │ ├── image.cpp │ ├── image.hpp │ ├── libyuv.cpp │ ├── libyuv.hpp │ ├── resize.cpp │ ├── resize.hpp │ ├── soundtouch.cpp │ ├── soundtouch.hpp │ ├── speexdsp.cpp │ ├── speexdsp.hpp │ ├── swresample.cpp │ ├── swresample.hpp │ ├── swscale.cpp │ └── swscale.hpp ├── util.cpp ├── util.hpp └── writer.cpp ├── decoder.go ├── decoderOpus.go ├── encoder.go ├── encoderFdkaac.go ├── encoderJpeg.go ├── encoderOpenh264.go ├── encoderOpus.go ├── encoderX264.go ├── encoderX265.go ├── frame.go ├── log.h ├── memo.md ├── reader.go ├── readme.md ├── resampler.go ├── resamplerImage.go ├── resamplerLibyuv.go ├── resamplerResizer.go ├── resamplerSoundtouch.go ├── resamplerSwscale.go ├── source.go ├── test ├── convert_test.go ├── decoder_test.go ├── encoder_test.go ├── fromBinary_test.go ├── reader_test.go ├── resampler_test.go ├── writer_test.go ├── x265check_test.go └── yuvclip_test.go ├── ttLibC.cpp ├── util.go ├── videoFrame.go ├── writer.go └── writerMpegts.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | *.webm 4 | *.mp4 5 | *.mkv 6 | *.flv 7 | *.ts 8 | build -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ttLibC"] 2 | path = ttLibC 3 | url = https://github.com/taktod/ttLibC.git 4 | -------------------------------------------------------------------------------- /build/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taktod/ttLibGo/ca2590d41630c0ba97790f22f5a484ec1e156c01/build/.gitkeep -------------------------------------------------------------------------------- /callback.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include "ttLibC/ttLibC/frame/frame.h" 5 | */ 6 | import "C" 7 | import ( 8 | "unsafe" 9 | ) 10 | 11 | // FrameCallback フレームが生成されたときのcallback動作 12 | //type FrameCallback func(frame *Frame) bool 13 | 14 | // DataCallback binaryデータが生成されたときのcallback動作 15 | //type DataCallback func(data []byte) bool 16 | 17 | // frameCall c言語側でのフレーム生成callbackの処理で利用する構造体 18 | // これを利用してgoの世界に戻す 19 | type frameCall struct { 20 | callback func(frame *Frame) bool 21 | } 22 | 23 | //export ttLibGoFrameCallback 24 | func ttLibGoFrameCallback(any unsafe.Pointer, cFrame *C.ttLibC_Frame) C.bool { 25 | // c言語側に渡してたvoid*にいれてる参照からgoで利用するcallbackを復元する 26 | if cFrame == nil { 27 | panic("frameができてないのに、frameCallbackが呼ばれました。") 28 | } 29 | call := (*frameCall)(any) 30 | // goで利用可能なフレームの形にして応答する 31 | frame := new(Frame) 32 | frame.init(cttLibCFrame(cFrame)) 33 | return C.bool(call.callback(frame)) 34 | } 35 | 36 | // dataCall c言語側でbinaryデータを取得したときにgoの世界に戻すための構造体 37 | type dataCall struct { 38 | callback func(data []byte) bool 39 | } 40 | 41 | //export ttLibGoDataCallback 42 | func ttLibGoDataCallback(any unsafe.Pointer, data unsafe.Pointer, dataSize C.size_t) C.bool { 43 | call := (*dataCall)(any) 44 | gData := C.GoBytes(data, C.int(dataSize)) 45 | return C.bool(call.callback(gData)) 46 | } 47 | -------------------------------------------------------------------------------- /cppsrc/decoder.cpp: -------------------------------------------------------------------------------- 1 | #include "ttLibC/ttLibC/allocator.h" 2 | #include "ttLibC/ttLibC/frame/frame.h" 3 | #include "ttLibC/ttLibC/frame/video/video.h" 4 | #include "ttLibC/ttLibC/frame/video/bgr.h" 5 | #include "ttLibC/ttLibC/frame/video/flv1.h" 6 | #include "ttLibC/ttLibC/frame/video/h264.h" 7 | #include "ttLibC/ttLibC/frame/video/h265.h" 8 | #include "ttLibC/ttLibC/frame/video/theora.h" 9 | #include "ttLibC/ttLibC/frame/video/yuv420.h" 10 | #include "ttLibC/ttLibC/frame/audio/audio.h" 11 | #include "ttLibC/ttLibC/frame/audio/aac.h" 12 | #include "ttLibC/ttLibC/frame/audio/mp3.h" 13 | #include "ttLibC/ttLibC/frame/audio/opus.h" 14 | #include "ttLibC/ttLibC/frame/audio/pcmf32.h" 15 | #include "ttLibC/ttLibC/frame/audio/pcms16.h" 16 | #include "ttLibC/ttLibC/frame/audio/speex.h" 17 | #include "ttLibC/ttLibC/frame/audio/vorbis.h" 18 | #include 19 | 20 | #include "decoder.hpp" 21 | #include "decoder/avcodec.hpp" 22 | #include "decoder/jpeg.hpp" 23 | #include "decoder/openh264.hpp" 24 | #include "decoder/opus.hpp" 25 | #include "decoder/png.hpp" 26 | #include "decoder/speex.hpp" 27 | #include "decoder/theora.hpp" 28 | #include "decoder/vorbis.hpp" 29 | 30 | using namespace std; 31 | 32 | Decoder *Decoder::create(maps *mp) { 33 | string decoderType = mp->getString("decoder"); 34 | if(decoderType == "avcodecVideo" || decoderType == "avcodecAudio") { 35 | return new AvcodecDecoder(mp); 36 | } 37 | else if(decoderType == "jpeg") { 38 | return new JpegDecoder(mp); 39 | } 40 | else if(decoderType == "openh264") { 41 | return new Openh264Decoder(mp); 42 | } 43 | else if(decoderType == "opus") { 44 | return new tOpusDecoder(mp); 45 | } 46 | else if(decoderType == "png") { 47 | return new PngDecoder(mp); 48 | } 49 | else if(decoderType == "speex") { 50 | return new SpeexDecoder(mp); 51 | } 52 | else if(decoderType == "theora") { 53 | return new TheoraDecoder(mp); 54 | } 55 | else if(decoderType == "vorbis") { 56 | return new VorbisDecoder(mp); 57 | } 58 | return nullptr; 59 | } 60 | Decoder::Decoder(){ 61 | } 62 | Decoder::~Decoder() { 63 | } 64 | 65 | extern "C" { 66 | 67 | void *Decoder_make(void *mp) { 68 | maps *m = reinterpret_cast(mp); 69 | return Decoder::create(m); 70 | } 71 | bool Decoder_decodeFrame(void *decoder, void *frame, void *goFrame, uintptr_t ptr) { 72 | if(decoder == nullptr) { 73 | return false; 74 | } 75 | Decoder *d = reinterpret_cast(decoder); 76 | ttLibC_Frame *cF = reinterpret_cast(frame); 77 | ttLibGoFrame *goF = reinterpret_cast(goFrame); 78 | return d->decodeFrame(cF, goF, (void *)ptr); 79 | } 80 | 81 | void Decoder_close(void *decoder) { 82 | if(decoder == nullptr) { 83 | return; 84 | } 85 | Decoder *d = reinterpret_cast(decoder); 86 | delete d; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /cppsrc/decoder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_HPP 2 | #define TTLIBGO_DECODER_HPP 3 | 4 | #include "util.hpp" 5 | #include "ttLibC/ttLibC/frame/frame.h" 6 | #include "frame.hpp" 7 | 8 | class Decoder : public FrameProcessor { 9 | public: 10 | static Decoder *create(maps *m); 11 | Decoder(); 12 | virtual ~Decoder(); 13 | virtual bool decodeFrame( 14 | ttLibC_Frame *cFrame, 15 | ttLibGoFrame *goFrame, 16 | void *ptr) = 0; 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /cppsrc/decoder/avcodec.cpp: -------------------------------------------------------------------------------- 1 | #include "avcodec.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_AvcodecDecoder_make_func)(ttLibC_Frame_Type, uint32_t, uint32_t); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | typedef bool (* ttLibC_isType_func)(ttLibC_Frame_Type); 13 | 14 | extern ttLibC_AvcodecDecoder_make_func ttLibGo_AvcodecVideoDecoder_make; 15 | extern ttLibC_AvcodecDecoder_make_func ttLibGo_AvcodecAudioDecoder_make; 16 | extern ttLibC_codec_func ttLibGo_AvcodecDecoder_decode; 17 | extern ttLibC_close_func ttLibGo_AvcodecDecoder_close; 18 | extern ttLibC_isType_func ttLibGo_isAudio; 19 | extern ttLibC_isType_func ttLibGo_isVideo; 20 | 21 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 22 | } 23 | AvcodecDecoder::AvcodecDecoder(maps *mp) { 24 | if(ttLibGo_AvcodecVideoDecoder_make != nullptr && ttLibGo_AvcodecAudioDecoder_make != nullptr 25 | && ttLibGo_isAudio != nullptr && ttLibGo_isVideo != nullptr) { 26 | ttLibC_Frame_Type type = Frame_getFrameTypeFromString(mp->getString("frameType")); 27 | if((*ttLibGo_isAudio)(type)) { 28 | _decoder = (*ttLibGo_AvcodecAudioDecoder_make)( 29 | type, 30 | mp->getUint32("sampleRate"), 31 | mp->getUint32("channelNum")); 32 | } 33 | else if((*ttLibGo_isVideo)(type)) { 34 | _decoder = (*ttLibGo_AvcodecVideoDecoder_make)( 35 | type, 36 | mp->getUint32("width"), 37 | mp->getUint32("height")); 38 | } 39 | } 40 | } 41 | 42 | AvcodecDecoder::~AvcodecDecoder() { 43 | if(ttLibGo_AvcodecDecoder_close != nullptr) { 44 | (*ttLibGo_AvcodecDecoder_close)(&_decoder); 45 | } 46 | } 47 | bool AvcodecDecoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 48 | bool result = false; 49 | if(ttLibGo_AvcodecDecoder_decode != nullptr) { 50 | update(cFrame, goFrame); 51 | result = (*ttLibGo_AvcodecDecoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 52 | reset(cFrame, goFrame); 53 | } 54 | return result; 55 | } 56 | -------------------------------------------------------------------------------- /cppsrc/decoder/avcodec.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_AVCODEC_HPP 2 | #define TTLIBGO_DECODER_AVCODEC_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class AvcodecDecoder : public Decoder { 7 | public: 8 | AvcodecDecoder(maps *mp); 9 | ~AvcodecDecoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_decoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/decoder/jpeg.cpp: -------------------------------------------------------------------------------- 1 | #include "jpeg.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_make_func)(); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_make_func ttLibGo_JpegDecoder_make; 14 | extern ttLibC_codec_func ttLibGo_JpegDecoder_decode; 15 | extern ttLibC_close_func ttLibGo_JpegDecoder_close; 16 | 17 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 18 | } 19 | JpegDecoder::JpegDecoder(maps *mp) { 20 | if(ttLibGo_JpegDecoder_make != nullptr) { 21 | _decoder = (*ttLibGo_JpegDecoder_make)(); 22 | } 23 | } 24 | JpegDecoder::~JpegDecoder() { 25 | if(ttLibGo_JpegDecoder_close != nullptr) { 26 | (*ttLibGo_JpegDecoder_close)(&_decoder); 27 | } 28 | } 29 | bool JpegDecoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 30 | bool result = false; 31 | if(ttLibGo_JpegDecoder_decode != nullptr) { 32 | update(cFrame, goFrame); 33 | result = (*ttLibGo_JpegDecoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 34 | reset(cFrame, goFrame); 35 | } 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /cppsrc/decoder/jpeg.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_JPEG_HPP 2 | #define TTLIBGO_DECODER_JPEG_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class JpegDecoder : public Decoder { 7 | public: 8 | JpegDecoder(maps *mp); 9 | ~JpegDecoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_decoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/decoder/openh264.cpp: -------------------------------------------------------------------------------- 1 | #include "openh264.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_make_func)(); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_make_func ttLibGo_Openh264Decoder_make; 14 | extern ttLibC_codec_func ttLibGo_Openh264Decoder_decode; 15 | extern ttLibC_close_func ttLibGo_Openh264Decoder_close; 16 | 17 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 18 | } 19 | Openh264Decoder::Openh264Decoder(maps *mp) { 20 | if(ttLibGo_Openh264Decoder_make != nullptr) { 21 | _decoder = (*ttLibGo_Openh264Decoder_make)(); 22 | } 23 | } 24 | Openh264Decoder::~Openh264Decoder() { 25 | if(ttLibGo_Openh264Decoder_close != nullptr) { 26 | (*ttLibGo_Openh264Decoder_close)(&_decoder); 27 | } 28 | } 29 | bool Openh264Decoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 30 | bool result = false; 31 | if(ttLibGo_Openh264Decoder_decode != nullptr) { 32 | update(cFrame, goFrame); 33 | result = (*ttLibGo_Openh264Decoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 34 | reset(cFrame, goFrame); 35 | } 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /cppsrc/decoder/openh264.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_OPENH264_HPP 2 | #define TTLIBGO_DECODER_OPENH264_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class Openh264Decoder : public Decoder { 7 | public: 8 | Openh264Decoder(maps *mp); 9 | ~Openh264Decoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_decoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/decoder/opus.cpp: -------------------------------------------------------------------------------- 1 | #include "opus.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_OpusDecoder_make_func)(uint32_t, uint32_t); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef int (* ttLibC_opus_codecControl_func)(void *, const char *, int); 12 | typedef void (* ttLibC_close_func)(void **); 13 | 14 | extern ttLibC_OpusDecoder_make_func ttLibGo_OpusDecoder_make; 15 | extern ttLibC_codec_func ttLibGo_OpusDecoder_decode; 16 | extern ttLibC_close_func ttLibGo_OpusDecoder_close; 17 | extern ttLibC_opus_codecControl_func ttLibGo_OpusDecoder_codecControl; 18 | 19 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 20 | } 21 | tOpusDecoder::tOpusDecoder(maps *mp) { 22 | if(ttLibGo_OpusDecoder_make != nullptr) { 23 | _decoder = (*ttLibGo_OpusDecoder_make)(mp->getUint32("sampleRate"), mp->getUint32("channelNum")); 24 | } 25 | } 26 | tOpusDecoder::~tOpusDecoder() { 27 | if(ttLibGo_OpusDecoder_close != nullptr) { 28 | (*ttLibGo_OpusDecoder_close)(&_decoder); 29 | } 30 | } 31 | bool tOpusDecoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 32 | bool result = false; 33 | if(ttLibGo_OpusDecoder_decode != nullptr) { 34 | update(cFrame, goFrame); 35 | result = (*ttLibGo_OpusDecoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 36 | reset(cFrame, goFrame); 37 | } 38 | return result; 39 | } 40 | 41 | int tOpusDecoder::codecControl(string control, int value) { 42 | if(ttLibGo_OpusDecoder_codecControl != nullptr) { 43 | if(_decoder == NULL) { 44 | puts("decoderが準備されていません。"); 45 | return -1; 46 | } 47 | return (*ttLibGo_OpusDecoder_codecControl)(_decoder, control.c_str(), value); 48 | } 49 | return -1; 50 | } 51 | 52 | extern "C" { 53 | int OpusDecoder_codecControl(void *decoder, const char *key, int value) { 54 | tOpusDecoder *d = reinterpret_cast(decoder); 55 | return d->codecControl(key, value); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cppsrc/decoder/opus.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_OPUS_HPP 2 | #define TTLIBGO_DECODER_OPUS_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class tOpusDecoder : public Decoder { 7 | public: 8 | tOpusDecoder(maps *mp); 9 | ~tOpusDecoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | int codecControl(string control, int value); 12 | private: 13 | void *_decoder; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cppsrc/decoder/png.cpp: -------------------------------------------------------------------------------- 1 | #include "png.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_make_func)(); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_make_func ttLibGo_PngDecoder_make; 14 | extern ttLibC_codec_func ttLibGo_PngDecoder_decode; 15 | extern ttLibC_close_func ttLibGo_PngDecoder_close; 16 | 17 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 18 | } 19 | PngDecoder::PngDecoder(maps *mp) { 20 | if(ttLibGo_PngDecoder_make != nullptr) { 21 | _decoder = (*ttLibGo_PngDecoder_make)(); 22 | } 23 | } 24 | PngDecoder::~PngDecoder() { 25 | if(ttLibGo_PngDecoder_close != nullptr) { 26 | (*ttLibGo_PngDecoder_close)(&_decoder); 27 | } 28 | } 29 | bool PngDecoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 30 | bool result = false; 31 | if(ttLibGo_PngDecoder_decode != nullptr) { 32 | update(cFrame, goFrame); 33 | result = (*ttLibGo_PngDecoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 34 | reset(cFrame, goFrame); 35 | } 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /cppsrc/decoder/png.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_PNG_HPP 2 | #define TTLIBGO_DECODER_PNG_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class PngDecoder : public Decoder { 7 | public: 8 | PngDecoder(maps *mp); 9 | ~PngDecoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_decoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/decoder/speex.cpp: -------------------------------------------------------------------------------- 1 | #include "speex.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_SpeexDecoder_make_func)(uint32_t, uint32_t); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_SpeexDecoder_make_func ttLibGo_SpeexDecoder_make; 14 | extern ttLibC_codec_func ttLibGo_SpeexDecoder_decode; 15 | extern ttLibC_close_func ttLibGo_SpeexDecoder_close; 16 | 17 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 18 | } 19 | SpeexDecoder::SpeexDecoder(maps *mp) { 20 | if(ttLibGo_SpeexDecoder_make != nullptr) { 21 | _decoder = (*ttLibGo_SpeexDecoder_make)(mp->getUint32("sampleRate"), mp->getUint32("channelNum")); 22 | } 23 | } 24 | SpeexDecoder::~SpeexDecoder() { 25 | if(ttLibGo_SpeexDecoder_close != nullptr) { 26 | (*ttLibGo_SpeexDecoder_close)(&_decoder); 27 | } 28 | } 29 | bool SpeexDecoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 30 | bool result = false; 31 | if(ttLibGo_SpeexDecoder_decode != nullptr) { 32 | update(cFrame, goFrame); 33 | result = (*ttLibGo_SpeexDecoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 34 | reset(cFrame, goFrame); 35 | } 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /cppsrc/decoder/speex.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_SPEEX_HPP 2 | #define TTLIBGO_DECODER_SPEEX_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class SpeexDecoder : public Decoder { 7 | public: 8 | SpeexDecoder(maps *mp); 9 | ~SpeexDecoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_decoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/decoder/theora.cpp: -------------------------------------------------------------------------------- 1 | #include "theora.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_make_func)(); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_make_func ttLibGo_TheoraDecoder_make; 14 | extern ttLibC_codec_func ttLibGo_TheoraDecoder_decode; 15 | extern ttLibC_close_func ttLibGo_TheoraDecoder_close; 16 | 17 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 18 | } 19 | TheoraDecoder::TheoraDecoder(maps *mp) { 20 | if(ttLibGo_TheoraDecoder_make != nullptr) { 21 | _decoder = (*ttLibGo_TheoraDecoder_make)(); 22 | } 23 | } 24 | TheoraDecoder::~TheoraDecoder() { 25 | if(ttLibGo_TheoraDecoder_close != nullptr) { 26 | (*ttLibGo_TheoraDecoder_close)(&_decoder); 27 | } 28 | } 29 | bool TheoraDecoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 30 | bool result = false; 31 | if(ttLibGo_TheoraDecoder_decode != nullptr) { 32 | update(cFrame, goFrame); 33 | result = (*ttLibGo_TheoraDecoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 34 | reset(cFrame, goFrame); 35 | } 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /cppsrc/decoder/theora.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_THEORA_HPP 2 | #define TTLIBGO_DECODER_THEORA_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class TheoraDecoder : public Decoder { 7 | public: 8 | TheoraDecoder(maps *mp); 9 | ~TheoraDecoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_decoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/decoder/vorbis.cpp: -------------------------------------------------------------------------------- 1 | #include "vorbis.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_make_func)(); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_make_func ttLibGo_VorbisDecoder_make; 14 | extern ttLibC_codec_func ttLibGo_VorbisDecoder_decode; 15 | extern ttLibC_close_func ttLibGo_VorbisDecoder_close; 16 | 17 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 18 | } 19 | VorbisDecoder::VorbisDecoder(maps *mp) { 20 | if(ttLibGo_VorbisDecoder_make != nullptr) { 21 | _decoder = (*ttLibGo_VorbisDecoder_make)(); 22 | } 23 | } 24 | VorbisDecoder::~VorbisDecoder() { 25 | if(ttLibGo_VorbisDecoder_close != nullptr) { 26 | (*ttLibGo_VorbisDecoder_close)(&_decoder); 27 | } 28 | } 29 | bool VorbisDecoder::decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 30 | bool result = false; 31 | if(ttLibGo_VorbisDecoder_decode != nullptr) { 32 | update(cFrame, goFrame); 33 | result = (*ttLibGo_VorbisDecoder_decode)(_decoder, cFrame, ttLibGoFrameCallback, ptr); 34 | reset(cFrame, goFrame); 35 | } 36 | return result; 37 | } 38 | -------------------------------------------------------------------------------- /cppsrc/decoder/vorbis.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_DECODER_VORBIS_HPP 2 | #define TTLIBGO_DECODER_VORBIS_HPP 3 | 4 | #include "../decoder.hpp" 5 | 6 | class VorbisDecoder : public Decoder { 7 | public: 8 | VorbisDecoder(maps *mp); 9 | ~VorbisDecoder(); 10 | bool decodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_decoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/encoder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ttLibC/ttLibC/allocator.h" 3 | #include "ttLibC/ttLibC/frame/frame.h" 4 | #include "ttLibC/ttLibC/frame/video/video.h" 5 | #include "ttLibC/ttLibC/frame/video/bgr.h" 6 | #include "ttLibC/ttLibC/frame/video/flv1.h" 7 | #include "ttLibC/ttLibC/frame/video/h264.h" 8 | #include "ttLibC/ttLibC/frame/video/h265.h" 9 | #include "ttLibC/ttLibC/frame/video/theora.h" 10 | #include "ttLibC/ttLibC/frame/video/yuv420.h" 11 | #include "ttLibC/ttLibC/frame/audio/audio.h" 12 | #include "ttLibC/ttLibC/frame/audio/aac.h" 13 | #include "ttLibC/ttLibC/frame/audio/mp3.h" 14 | #include "ttLibC/ttLibC/frame/audio/opus.h" 15 | #include "ttLibC/ttLibC/frame/audio/pcmf32.h" 16 | #include "ttLibC/ttLibC/frame/audio/pcms16.h" 17 | #include "ttLibC/ttLibC/frame/audio/speex.h" 18 | #include "ttLibC/ttLibC/frame/audio/vorbis.h" 19 | #include 20 | 21 | #include "encoder.hpp" 22 | #include "encoder/fdkaac.hpp" 23 | #include "encoder/jpeg.hpp" 24 | #include "encoder/openh264.hpp" 25 | #include "encoder/opus.hpp" 26 | #include "encoder/speex.hpp" 27 | #include "encoder/theora.hpp" 28 | #include "encoder/vorbis.hpp" 29 | #include "encoder/x264.hpp" 30 | #include "encoder/x265.hpp" 31 | 32 | #include 33 | 34 | using namespace std; 35 | 36 | Encoder *Encoder::create(maps *mp) { 37 | string encoderType = mp->getString("encoder"); 38 | if(encoderType == "fdkaac") { 39 | return new FdkaacEncoder(mp); 40 | } 41 | else if(encoderType == "jpeg") { 42 | return new JpegEncoder(mp); 43 | } 44 | else if(encoderType == "openh264") { 45 | return new Openh264Encoder(mp); 46 | } 47 | else if(encoderType == "opus") { 48 | return new tOpusEncoder(mp); 49 | } 50 | else if(encoderType == "speex") { 51 | return new SpeexEncoder(mp); 52 | } 53 | else if(encoderType == "theora") { 54 | return new TheoraEncoder(mp); 55 | } 56 | else if(encoderType == "vorbis") { 57 | return new VorbisEncoder(mp); 58 | } 59 | else if(encoderType == "x264") { 60 | return new X264Encoder(mp); 61 | } 62 | else if(encoderType == "x265") { 63 | return new X265Encoder(mp); 64 | } 65 | return nullptr; 66 | } 67 | Encoder::Encoder() { 68 | } 69 | Encoder::~Encoder() { 70 | } 71 | 72 | extern "C" { 73 | void *Encoder_make(void *mp) { 74 | maps *m = reinterpret_cast(mp); 75 | return Encoder::create(m); 76 | } 77 | bool Encoder_encodeFrame(void *encoder, void *frame, void *goFrame, uintptr_t ptr) { 78 | if(encoder == nullptr) { 79 | return false; 80 | } 81 | Encoder *e = reinterpret_cast(encoder); 82 | ttLibC_Frame *cF = reinterpret_cast(frame); 83 | ttLibGoFrame *goF = reinterpret_cast(goFrame); 84 | return e->encodeFrame(cF, goF, (void *)ptr); 85 | } 86 | void Encoder_close(void *encoder) { 87 | if(encoder == nullptr) { 88 | return; 89 | } 90 | Encoder *e = reinterpret_cast(encoder); 91 | delete e; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /cppsrc/encoder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_HPP 2 | #define TTLIBGO_ENCODER_HPP 3 | 4 | #include "util.hpp" 5 | #include "ttLibC/ttLibC/frame/frame.h" 6 | #include "frame.hpp" 7 | 8 | class Encoder : public FrameProcessor { 9 | public: 10 | static Encoder *create(maps *m); 11 | Encoder(); 12 | virtual ~Encoder(); 13 | virtual bool encodeFrame( 14 | ttLibC_Frame *cFrame, 15 | ttLibGoFrame *goFrame, 16 | void *ptr) = 0; 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /cppsrc/encoder/fdkaac.cpp: -------------------------------------------------------------------------------- 1 | #include "fdkaac.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_FdkaacEncoder_make_func)(const char *,uint32_t,uint32_t,uint32_t); 10 | typedef bool (* ttLibC_FdkaacEncoder_setBitrate_func)(void *,uint32_t); 11 | typedef void (* ttLibC_close_func)(void **); 12 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 13 | 14 | extern ttLibC_FdkaacEncoder_make_func ttLibGo_FdkaacEncoder_make; 15 | extern ttLibC_codec_func ttLibGo_FdkaacEncoder_encode; 16 | extern ttLibC_close_func ttLibGo_FdkaacEncoder_close; 17 | extern ttLibC_FdkaacEncoder_setBitrate_func ttLibGo_FdkaacEncoder_setBitrate; 18 | 19 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 20 | } 21 | FdkaacEncoder::FdkaacEncoder(maps *mp) { 22 | if(ttLibGo_FdkaacEncoder_make != nullptr) { 23 | string type = mp->getString("aacType"); 24 | uint32_t sampleRate = mp->getUint32("sampleRate"); 25 | uint32_t channelNum = mp->getUint32("channelNum"); 26 | uint32_t bitrate = mp->getUint32("bitrate"); 27 | _encoder = (*ttLibGo_FdkaacEncoder_make)(type.c_str(), sampleRate, channelNum, bitrate); 28 | } 29 | } 30 | 31 | FdkaacEncoder::~FdkaacEncoder() { 32 | if(ttLibGo_FdkaacEncoder_close != nullptr) { 33 | (*ttLibGo_FdkaacEncoder_close)(&_encoder); 34 | } 35 | } 36 | bool FdkaacEncoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 37 | bool result = false; 38 | if(ttLibGo_FdkaacEncoder_encode != nullptr) { 39 | if(cFrame->type != frameType_pcmS16) { 40 | return result; 41 | } 42 | update(cFrame, goFrame); 43 | result = (*ttLibGo_FdkaacEncoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 44 | reset(cFrame, goFrame); 45 | } 46 | return result; 47 | } 48 | 49 | bool FdkaacEncoder::setBitrate(uint32_t value) { 50 | if(ttLibGo_FdkaacEncoder_setBitrate != nullptr) { 51 | return (* ttLibGo_FdkaacEncoder_setBitrate)(_encoder, value); 52 | } 53 | return false; 54 | } 55 | extern "C" { 56 | bool FdkaacEncoder_setBitrate(void *encoder, uint32_t value) { 57 | FdkaacEncoder *fdk = reinterpret_cast(encoder); 58 | return fdk->setBitrate(value); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /cppsrc/encoder/fdkaac.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_FDKAAC_HPP 2 | #define TTLIBGO_ENCODER_FDKAAC_HPP 3 | 4 | #include "../encoder.hpp" 5 | #include "ttLibC/ttLibC/frame/audio/aac.h" 6 | 7 | class FdkaacEncoder : public Encoder { 8 | public: 9 | FdkaacEncoder(maps *mp); 10 | ~FdkaacEncoder(); 11 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 12 | bool setBitrate(uint32_t value); 13 | private: 14 | void *_encoder; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /cppsrc/encoder/jpeg.cpp: -------------------------------------------------------------------------------- 1 | #include "jpeg.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_JpegEncoder_make_func)(uint32_t, uint32_t, uint32_t); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void *(* ttLibC_JpegEncoder_setQuality_func)(void *, uint32_t); 12 | typedef void (* ttLibC_close_func)(void **); 13 | 14 | extern ttLibC_JpegEncoder_make_func ttLibGo_JpegEncoder_make; 15 | extern ttLibC_codec_func ttLibGo_JpegEncoder_encode; 16 | extern ttLibC_JpegEncoder_setQuality_func ttLibGo_JpegEncoder_setQuality; 17 | extern ttLibC_close_func ttLibGo_JpegEncoder_close; 18 | 19 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 20 | } 21 | JpegEncoder::JpegEncoder(maps *mp) { 22 | if(ttLibGo_JpegEncoder_make != nullptr) { 23 | _encoder = (*ttLibGo_JpegEncoder_make)(mp->getUint32("width"), mp->getUint32("height"), mp->getUint32("quality")); 24 | } 25 | } 26 | 27 | JpegEncoder::~JpegEncoder() { 28 | if(ttLibGo_JpegEncoder_close != nullptr) { 29 | (*ttLibGo_JpegEncoder_close)(&_encoder); 30 | } 31 | } 32 | bool JpegEncoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 33 | bool result = false; 34 | if(ttLibGo_JpegEncoder_encode != nullptr) { 35 | if(cFrame->type != frameType_yuv420) { 36 | return result; 37 | } 38 | update(cFrame, goFrame); 39 | result = (*ttLibGo_JpegEncoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 40 | reset(cFrame, goFrame); 41 | } 42 | return result; 43 | } 44 | 45 | bool JpegEncoder::setQuality(uint32_t quality) { 46 | bool result = false; 47 | if(ttLibGo_JpegEncoder_setQuality != nullptr) { 48 | result = (*ttLibGo_JpegEncoder_setQuality)(_encoder, quality); 49 | } 50 | return result; 51 | } 52 | 53 | extern "C" { 54 | bool JpegEncoder_setQuality(void *encoder, uint32_t quality) { 55 | JpegEncoder *j = reinterpret_cast(encoder); 56 | return j->setQuality(quality); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /cppsrc/encoder/jpeg.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_JPEG_HPP 2 | #define TTLIBGO_ENCODER_JPEG_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class JpegEncoder : public Encoder { 7 | public: 8 | JpegEncoder(maps *mp); 9 | ~JpegEncoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | bool setQuality(uint32_t quality); 12 | private: 13 | void *_encoder; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cppsrc/encoder/openh264.cpp: -------------------------------------------------------------------------------- 1 | #include "openh264.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include 5 | #include "ttLibC/ttLibC/container/container.h" 6 | #include "ttLibC/ttLibC/encoder/openh264Encoder.h" 7 | 8 | using namespace std; 9 | 10 | extern "C" { 11 | typedef void (* ttLibC_Openh264Encoder_getDefaultSEncParamExt_func)(void *, uint32_t, uint32_t); 12 | typedef bool (* ttLibC_Openh264Encoder_paramParse_func)(void *, const char *, const char *); 13 | typedef bool (* ttLibC_Openh264Encoder_spatialParamParse_func)(void *, uint32_t, const char *, const char *); 14 | typedef void *(* ttLibC_Openh264Encoder_makeWithSEncParamExt_func)(void *); 15 | typedef bool (* ttLibC_Openh264Encoder_setRCMode_func)(void *, ttLibC_Openh264Encoder_RCType); 16 | typedef bool (* ttLibC_Openh264Encoder_setIDRInterval_func)(void *, uint32_t); 17 | typedef bool (* ttLibC_Openh264Encoder_forceNextKeyFrame_func)(void *); 18 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 19 | typedef void (* ttLibC_close_func)(void **); 20 | 21 | extern ttLibC_Openh264Encoder_getDefaultSEncParamExt_func ttLibGo_Openh264Encoder_getDefaultSEncParamExt; 22 | extern ttLibC_Openh264Encoder_paramParse_func ttLibGo_Openh264Encoder_paramParse; 23 | extern ttLibC_Openh264Encoder_spatialParamParse_func ttLibGo_Openh264Encoder_spatialParamParse; 24 | extern ttLibC_Openh264Encoder_makeWithSEncParamExt_func ttLibGo_Openh264Encoder_makeWithSEncParamExt; 25 | extern ttLibC_codec_func ttLibGo_Openh264Encoder_encode; 26 | extern ttLibC_close_func ttLibGo_Openh264Encoder_close; 27 | extern ttLibC_Openh264Encoder_setRCMode_func ttLibGo_Openh264Encoder_setRCMode; 28 | extern ttLibC_Openh264Encoder_setIDRInterval_func ttLibGo_Openh264Encoder_setIDRInterval; 29 | extern ttLibC_Openh264Encoder_forceNextKeyFrame_func ttLibGo_Openh264Encoder_forceNextKeyFrame; 30 | 31 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 32 | } 33 | Openh264Encoder::Openh264Encoder(maps *mp) { 34 | if(ttLibGo_Openh264Encoder_getDefaultSEncParamExt != nullptr 35 | && ttLibGo_Openh264Encoder_paramParse != nullptr 36 | && ttLibGo_Openh264Encoder_spatialParamParse != nullptr 37 | && ttLibGo_Openh264Encoder_makeWithSEncParamExt != nullptr) { 38 | uint32_t width = mp->getUint32("width"); 39 | uint32_t height = mp->getUint32("height"); 40 | list params = mp->getStringList("param"); 41 | list spatialParamArrays = mp->getStringList("spatialParamArray"); 42 | if(width == 0 || height == 0) { 43 | return; 44 | } 45 | // SEncParamExt paramExt; 46 | // printf("%d\n", sizeof(SEncParamExt)); // 916 byteらしい。 47 | char paramExt[4096]; // とりあえず、charで大きめに保持しておいて、誤魔化す。 48 | // width height params spatialParamsArrayが必要 49 | (*ttLibGo_Openh264Encoder_getDefaultSEncParamExt)(¶mExt, width, height); 50 | regex r(R"([^:]+):([^:]+)"); 51 | for(auto iter = params.cbegin(); iter != params.cend();++ iter) { 52 | sregex_iterator reg_iter(iter->begin(), iter->end(), r); 53 | string key = reg_iter->str(); 54 | reg_iter ++; 55 | string value = reg_iter->str(); 56 | bool result = (*ttLibGo_Openh264Encoder_paramParse)(¶mExt, key.c_str(), value.c_str()); 57 | if(!result) { 58 | cout << "パラメーター設定失敗:" << key << ":" << value << endl; 59 | } 60 | } 61 | regex sr(R"([^:]+):([^:]+):([^:]+)"); 62 | for(auto iter = spatialParamArrays.cbegin();iter != spatialParamArrays.cend();++ iter) { 63 | sregex_iterator reg_iter(iter->begin(), iter->end(), r); 64 | string num = reg_iter->str(); 65 | reg_iter ++; 66 | string key = reg_iter->str(); 67 | reg_iter ++; 68 | string value = reg_iter->str(); 69 | bool result = (*ttLibGo_Openh264Encoder_spatialParamParse)(¶mExt, stoi(num), key.c_str(), value.c_str()); 70 | if(!result) { 71 | cout << "パラメーター設定失敗:" << key << ":" << value << endl; 72 | } 73 | } 74 | _encoder = (*ttLibGo_Openh264Encoder_makeWithSEncParamExt)(¶mExt); 75 | } 76 | } 77 | 78 | Openh264Encoder::~Openh264Encoder() { 79 | if(ttLibGo_Openh264Encoder_close != nullptr) { 80 | (*ttLibGo_Openh264Encoder_close)(&_encoder); 81 | } 82 | } 83 | bool Openh264Encoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 84 | bool result = false; 85 | if(ttLibGo_Openh264Encoder_encode != nullptr) { 86 | if(cFrame->type != frameType_yuv420) { 87 | return result; 88 | } 89 | update(cFrame, goFrame); 90 | result = (*ttLibGo_Openh264Encoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 91 | reset(cFrame, goFrame); 92 | } 93 | return result; 94 | } 95 | 96 | bool Openh264Encoder::setRCMode(string mode) { 97 | if(ttLibGo_Openh264Encoder_setRCMode != nullptr) { 98 | ttLibC_Openh264Encoder_RCType type; 99 | if(mode == "QualityMode") { 100 | type = Openh264EncoderRCType_QualityMode; 101 | } 102 | else if(mode == "BitrateMode") { 103 | type = Openh264EncoderRCType_BitrateMode; 104 | } 105 | else if(mode == "BufferbasedMode") { 106 | type = Openh264EncoderRCType_BufferbasedMode; 107 | } 108 | else if(mode == "TimestampMode") { 109 | type = Openh264EncoderRCType_TimestampMode; 110 | } 111 | else if(mode == "BitrateModePostSkip") { 112 | type = Openh264EncoderRCType_BitrateModePostSkip; 113 | } 114 | else if(mode == "OffMode") { 115 | type = Openh264EncoderRCType_OffMode; 116 | } 117 | else { 118 | return false; 119 | } 120 | return (*ttLibGo_Openh264Encoder_setRCMode)(_encoder, type); 121 | } 122 | return false; 123 | } 124 | bool Openh264Encoder::setIDRInterval(uint32_t value) { 125 | bool result = false; 126 | if(ttLibGo_Openh264Encoder_setIDRInterval != nullptr) { 127 | result = (*ttLibGo_Openh264Encoder_setIDRInterval)(_encoder, value); 128 | } 129 | return result; 130 | } 131 | bool Openh264Encoder::forceNextKeyFrame() { 132 | bool result = false; 133 | if(ttLibGo_Openh264Encoder_forceNextKeyFrame != nullptr) { 134 | (*ttLibGo_Openh264Encoder_forceNextKeyFrame)(_encoder); 135 | } 136 | return result; 137 | } 138 | 139 | extern "C" { 140 | bool Openh264Encoder_setRCMode(void *encoder, const char *mode) { 141 | Openh264Encoder *o = reinterpret_cast(encoder); 142 | return o->setRCMode(mode); 143 | } 144 | bool Openh264Encoder_setIDRInterval(void *encoder, uint32_t interval) { 145 | Openh264Encoder *o = reinterpret_cast(encoder); 146 | return o->setIDRInterval(interval); 147 | } 148 | bool Openh264Encoder_forceNextKeyFrame(void *encoder) { 149 | Openh264Encoder *o = reinterpret_cast(encoder); 150 | return o->forceNextKeyFrame(); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /cppsrc/encoder/openh264.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_OPENH264_HPP 2 | #define TTLIBGO_ENCODER_OPENH264_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class Openh264Encoder : public Encoder { 7 | public: 8 | Openh264Encoder(maps *mp); 9 | ~Openh264Encoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | bool setRCMode(string mode); 12 | bool setIDRInterval(uint32_t value); 13 | bool forceNextKeyFrame(); 14 | private: 15 | void *_encoder; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /cppsrc/encoder/opus.cpp: -------------------------------------------------------------------------------- 1 | #include "opus.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_OpusEncoder_make_func)(uint32_t, uint32_t, uint32_t); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef int (* ttLibC_opus_codecControl_func)(void *, const char *, int); 12 | typedef void (* ttLibC_close_func)(void **); 13 | 14 | extern ttLibC_OpusEncoder_make_func ttLibGo_OpusEncoder_make; 15 | extern ttLibC_codec_func ttLibGo_OpusEncoder_encode; 16 | extern ttLibC_opus_codecControl_func ttLibGo_OpusEncoder_codecControl; 17 | extern ttLibC_close_func ttLibGo_OpusEncoder_close; 18 | 19 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 20 | } 21 | tOpusEncoder::tOpusEncoder(maps *mp) { 22 | if(ttLibGo_OpusEncoder_make != nullptr) { 23 | _encoder = (*ttLibGo_OpusEncoder_make)(mp->getUint32("sampleRate"), mp->getUint32("channelNum"), mp->getUint32("unitSampleNum")); 24 | } 25 | } 26 | 27 | tOpusEncoder::~tOpusEncoder() { 28 | if(ttLibGo_OpusEncoder_close != nullptr) { 29 | (*ttLibGo_OpusEncoder_close)(&_encoder); 30 | } 31 | } 32 | bool tOpusEncoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 33 | bool result = false; 34 | if(ttLibGo_OpusEncoder_encode != nullptr) { 35 | if(cFrame->type != frameType_pcmS16) { 36 | return result; 37 | } 38 | update(cFrame, goFrame); 39 | result = (*ttLibGo_OpusEncoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 40 | reset(cFrame, goFrame); 41 | } 42 | return result; 43 | } 44 | 45 | int tOpusEncoder::codecControl(string control, int value) { 46 | if(ttLibGo_OpusEncoder_codecControl != nullptr) { 47 | return (*ttLibGo_OpusEncoder_codecControl)(_encoder, control.c_str(), value); 48 | } 49 | return -1; 50 | } 51 | 52 | extern "C" { 53 | int OpusEncoder_codecControl(void *encoder, const char *key, int value) { 54 | tOpusEncoder *e = reinterpret_cast(encoder); 55 | return e->codecControl(key, value); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /cppsrc/encoder/opus.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_OPUS_HPP 2 | #define TTLIBGO_ENCODER_OPUS_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class tOpusEncoder : public Encoder { 7 | public: 8 | tOpusEncoder(maps *mp); 9 | ~tOpusEncoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | int codecControl(string control, int value); 12 | private: 13 | void *_encoder; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cppsrc/encoder/speex.cpp: -------------------------------------------------------------------------------- 1 | #include "speex.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include "ttLibC/ttLibC/container/container.h" 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_SpeexEncoder_make_func)(uint32_t, uint32_t, uint32_t); 10 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_SpeexEncoder_make_func ttLibGo_SpeexEncoder_make; 14 | extern ttLibC_codec_func ttLibGo_SpeexEncoder_encode; 15 | extern ttLibC_close_func ttLibGo_SpeexEncoder_close; 16 | 17 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 18 | } 19 | SpeexEncoder::SpeexEncoder(maps *mp) { 20 | if(ttLibGo_SpeexEncoder_make != nullptr) { 21 | _encoder = (*ttLibGo_SpeexEncoder_make)(mp->getUint32("sampleRate"), mp->getUint32("channelNum"), mp->getUint32("quality")); 22 | } 23 | } 24 | 25 | SpeexEncoder::~SpeexEncoder() { 26 | if(ttLibGo_SpeexEncoder_close != nullptr) { 27 | (*ttLibGo_SpeexEncoder_close)(&_encoder); 28 | } 29 | } 30 | bool SpeexEncoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 31 | bool result = false; 32 | if(ttLibGo_SpeexEncoder_encode != nullptr) { 33 | if(cFrame->type != frameType_pcmS16) { 34 | return result; 35 | } 36 | update(cFrame, goFrame); 37 | result = (*ttLibGo_SpeexEncoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 38 | reset(cFrame, goFrame); 39 | } 40 | return result; 41 | } 42 | -------------------------------------------------------------------------------- /cppsrc/encoder/speex.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_SPEEX_HPP 2 | #define TTLIBGO_ENCODER_SPEEX_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class SpeexEncoder : public Encoder { 7 | public: 8 | SpeexEncoder(maps *mp); 9 | ~SpeexEncoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_encoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/encoder/theora.cpp: -------------------------------------------------------------------------------- 1 | #include "theora.hpp" 2 | #include "../util.hpp" 3 | #include 4 | 5 | using namespace std; 6 | 7 | extern "C" { 8 | typedef void *(* ttLibC_TheoraEncoder_make_ex_func)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); 9 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 10 | typedef void (* ttLibC_close_func)(void **); 11 | 12 | extern ttLibC_TheoraEncoder_make_ex_func ttLibGo_TheoraEncoder_make_ex; 13 | extern ttLibC_codec_func ttLibGo_TheoraEncoder_encode; 14 | extern ttLibC_close_func ttLibGo_TheoraEncoder_close; 15 | 16 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 17 | } 18 | TheoraEncoder::TheoraEncoder(maps *mp) { 19 | if(ttLibGo_TheoraEncoder_make_ex != nullptr) { 20 | _encoder = (*ttLibGo_TheoraEncoder_make_ex)( 21 | mp->getUint32("width"), 22 | mp->getUint32("height"), 23 | mp->getUint32("quality"), 24 | mp->getUint32("bitrate"), 25 | mp->getUint32("keyFrameInterval")); 26 | } 27 | } 28 | 29 | TheoraEncoder::~TheoraEncoder() { 30 | if(ttLibGo_TheoraEncoder_close != nullptr) { 31 | (*ttLibGo_TheoraEncoder_close)(&_encoder); 32 | } 33 | } 34 | bool TheoraEncoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 35 | bool result = false; 36 | if(ttLibGo_TheoraEncoder_encode != nullptr) { 37 | if(cFrame->type != frameType_yuv420) { 38 | return result; 39 | } 40 | update(cFrame, goFrame); 41 | result = (*ttLibGo_TheoraEncoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 42 | reset(cFrame, goFrame); 43 | } 44 | return result; 45 | } 46 | -------------------------------------------------------------------------------- /cppsrc/encoder/theora.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_THEORA_HPP 2 | #define TTLIBGO_ENCODER_THEORA_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class TheoraEncoder : public Encoder { 7 | public: 8 | TheoraEncoder(maps *mp); 9 | ~TheoraEncoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_encoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/encoder/vorbis.cpp: -------------------------------------------------------------------------------- 1 | #include "vorbis.hpp" 2 | #include "../util.hpp" 3 | #include 4 | 5 | using namespace std; 6 | 7 | extern "C" { 8 | typedef void *(* ttLibC_VorbisEncoder_make_func)(uint32_t, uint32_t); 9 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 10 | typedef void (* ttLibC_close_func)(void **); 11 | 12 | extern ttLibC_VorbisEncoder_make_func ttLibGo_VorbisEncoder_make; 13 | extern ttLibC_codec_func ttLibGo_VorbisEncoder_encode; 14 | extern ttLibC_close_func ttLibGo_VorbisEncoder_close; 15 | 16 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 17 | } 18 | VorbisEncoder::VorbisEncoder(maps *mp) { 19 | if(ttLibGo_VorbisEncoder_make != nullptr) { 20 | _encoder = (*ttLibGo_VorbisEncoder_make)(mp->getUint32("sampleRate"), mp->getUint32("channelNum")); 21 | } 22 | } 23 | 24 | VorbisEncoder::~VorbisEncoder() { 25 | if(ttLibGo_VorbisEncoder_close != nullptr) { 26 | (*ttLibGo_VorbisEncoder_close)(&_encoder); 27 | } 28 | } 29 | bool VorbisEncoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 30 | bool result = false; 31 | if(ttLibGo_VorbisEncoder_encode != nullptr) { 32 | if(cFrame->type != frameType_pcmS16 33 | && cFrame->type != frameType_pcmF32) { 34 | return result; 35 | } 36 | update(cFrame, goFrame); 37 | result = (*ttLibGo_VorbisEncoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 38 | reset(cFrame, goFrame); 39 | } 40 | return result; 41 | } 42 | -------------------------------------------------------------------------------- /cppsrc/encoder/vorbis.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_VORBIS_HPP 2 | #define TTLIBGO_ENCODER_VORBIS_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class VorbisEncoder : public Encoder { 7 | public: 8 | VorbisEncoder(maps *mp); 9 | ~VorbisEncoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | void *_encoder; 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /cppsrc/encoder/x264.cpp: -------------------------------------------------------------------------------- 1 | #include "x264.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include 5 | #include "ttLibC/ttLibC/container/container.h" 6 | #include "ttLibC/ttLibC/encoder/x264Encoder.h" 7 | 8 | using namespace std; 9 | 10 | extern "C" { 11 | typedef void (* ttLibC_X264Encoder_getDefaultX264ParamTWithPresetTune_func)(void *, uint32_t, uint32_t, const char *, const char *); 12 | typedef int (* ttLibC_X264Encoder_paramParse_func)(void *, const char *, const char *); 13 | typedef int (* ttLibC_X264Encoder_paramApplyProfile_func)(void *, const char *); 14 | typedef void *(* ttLibC_X264Encoder_makeWithX264ParamT_func)(void *); 15 | typedef bool (* ttLibC_X264Encoder_forceNextFrameType_func)(void *, ttLibC_X264Encoder_FrameType); 16 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 17 | typedef void (* ttLibC_close_func)(void **); 18 | 19 | extern ttLibC_X264Encoder_getDefaultX264ParamTWithPresetTune_func ttLibGo_X264Encoder_getDefaultX264ParamTWithPresetTune; 20 | extern ttLibC_X264Encoder_paramParse_func ttLibGo_X264Encoder_paramParse; 21 | extern ttLibC_X264Encoder_paramApplyProfile_func ttLibGo_X264Encoder_paramApplyProfile; 22 | extern ttLibC_X264Encoder_makeWithX264ParamT_func ttLibGo_X264Encoder_makeWithX264ParamT; 23 | extern ttLibC_codec_func ttLibGo_X264Encoder_encode; 24 | extern ttLibC_X264Encoder_forceNextFrameType_func ttLibGo_X264Encoder_forceNextFrameType; 25 | extern ttLibC_close_func ttLibGo_X264Encoder_close; 26 | 27 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 28 | } 29 | X264Encoder::X264Encoder(maps *mp) { 30 | if(ttLibGo_X264Encoder_getDefaultX264ParamTWithPresetTune != nullptr 31 | && ttLibGo_X264Encoder_paramParse != nullptr 32 | && ttLibGo_X264Encoder_paramApplyProfile != nullptr 33 | && ttLibGo_X264Encoder_makeWithX264ParamT != nullptr) { 34 | uint32_t width = mp->getUint32("width"); 35 | uint32_t height = mp->getUint32("height"); 36 | string preset = mp->getString("preset"); 37 | string tune = mp->getString("tune"); 38 | string profile = mp->getString("profile"); 39 | list params = mp->getStringList("param"); 40 | //x264_param_t x264Param; // 936 byteらしい・・・ 41 | char x264Param[4096]; 42 | (*ttLibGo_X264Encoder_getDefaultX264ParamTWithPresetTune)( 43 | &x264Param, 44 | width, 45 | height, 46 | preset.c_str(), 47 | tune.c_str()); 48 | regex r(R"([^:]+):(.+)"); 49 | for(auto iter = params.cbegin(); iter != params.cend();++ iter) { 50 | sregex_iterator reg_iter(iter->begin(), iter->end(), r); 51 | string key = reg_iter->str(); 52 | reg_iter ++; 53 | string value = reg_iter->str(); 54 | int result = (*ttLibGo_X264Encoder_paramParse)(&x264Param, key.c_str(), value.c_str()); 55 | if(result < 0) { 56 | cout << "パラメーター設定失敗:" << key << ":" << value << endl; 57 | } 58 | } 59 | if((*ttLibGo_X264Encoder_paramApplyProfile)(&x264Param, profile.c_str())) { 60 | cout << "profile apply失敗しました。" << endl; 61 | _encoder = NULL; 62 | } 63 | else { 64 | _encoder = (*ttLibGo_X264Encoder_makeWithX264ParamT)(&x264Param); 65 | } 66 | } 67 | } 68 | 69 | X264Encoder::~X264Encoder() { 70 | if(ttLibGo_X264Encoder_close != nullptr) { 71 | (*ttLibGo_X264Encoder_close)(&_encoder); 72 | } 73 | } 74 | bool X264Encoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 75 | bool result = false; 76 | if(ttLibGo_X264Encoder_encode != nullptr) { 77 | if(cFrame->type != frameType_yuv420) { 78 | return result; 79 | } 80 | update(cFrame, goFrame); 81 | result = (*ttLibGo_X264Encoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 82 | reset(cFrame, goFrame); 83 | } 84 | return result; 85 | } 86 | 87 | bool X264Encoder::forceNextFrameType(string type) { 88 | bool result = false; 89 | if(ttLibGo_X264Encoder_forceNextFrameType != nullptr) { 90 | ttLibC_X264Encoder_FrameType frameType = X264FrameType_Auto; 91 | if(type == "I") { 92 | frameType = X264FrameType_I; 93 | } 94 | else if(type == "P") { 95 | frameType = X264FrameType_P; 96 | } 97 | else if(type == "B") { 98 | frameType = X264FrameType_B; 99 | } 100 | else if(type == "IDR") { 101 | frameType = X264FrameType_IDR; 102 | } 103 | else if(type == "Auto") { 104 | frameType = X264FrameType_Auto; 105 | } 106 | else if(type == "Bref") { 107 | frameType = X264FrameType_Bref; 108 | } 109 | else if(type == "KeyFrame") { 110 | frameType = X264FrameType_KeyFrame; 111 | } 112 | else { 113 | return false; 114 | } 115 | result = (* ttLibGo_X264Encoder_forceNextFrameType)(_encoder, frameType); 116 | } 117 | return result; 118 | } 119 | 120 | extern "C" { 121 | bool X264Encoder_forceNextFrameType(void *encoder, const char *type) { 122 | X264Encoder *x = reinterpret_cast(encoder); 123 | return x->forceNextFrameType(type); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /cppsrc/encoder/x264.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_X264_HPP 2 | #define TTLIBGO_ENCODER_X264_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class X264Encoder : public Encoder { 7 | public: 8 | X264Encoder(maps *mp); 9 | ~X264Encoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | bool forceNextFrameType(string type); 12 | private: 13 | void *_encoder; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cppsrc/encoder/x265.cpp: -------------------------------------------------------------------------------- 1 | #include "x265.hpp" 2 | #include "../util.hpp" 3 | #include 4 | #include 5 | #include "ttLibC/ttLibC/container/container.h" 6 | #include "ttLibC/ttLibC/encoder/x265Encoder.h" 7 | 8 | using namespace std; 9 | 10 | extern "C" { 11 | typedef bool (* ttLibC_X265Encoder_getDefaultX265ApiAndParam_func)(void **, void **, const char *, const char *, uint32_t, uint32_t); 12 | typedef int (* ttLibC_X265Encoder_paramParse_func)(void *param, const char *key, const char *value); 13 | typedef int (* ttLibC_X265Encoder_paramApplyProfile_func)(void *param, const char *profile); 14 | typedef void *(* ttLibC_X265Encoder_makeWithX265ApiAndParam_func)(void *, void *); 15 | typedef bool (* ttLibC_X265Encoder_forceNextFrameType_func)(void *, ttLibC_X265Encoder_FrameType); 16 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 17 | typedef void (* ttLibC_close_func)(void **); 18 | 19 | extern ttLibC_X265Encoder_getDefaultX265ApiAndParam_func ttLibGo_X265Encoder_getDefaultX265ApiAndParam; 20 | extern ttLibC_X265Encoder_paramParse_func ttLibGo_X265Encoder_paramParse; 21 | extern ttLibC_X265Encoder_paramApplyProfile_func ttLibGo_X265Encoder_paramApplyProfile; 22 | extern ttLibC_X265Encoder_makeWithX265ApiAndParam_func ttLibGo_X265Encoder_makeWithX265ApiAndParam; 23 | extern ttLibC_codec_func ttLibGo_X265Encoder_encode; 24 | extern ttLibC_X265Encoder_forceNextFrameType_func ttLibGo_X265Encoder_forceNextFrameType; 25 | extern ttLibC_close_func ttLibGo_X265Encoder_close; 26 | 27 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 28 | } 29 | X265Encoder::X265Encoder(maps *mp) { 30 | if(ttLibGo_X265Encoder_getDefaultX265ApiAndParam != nullptr 31 | && ttLibGo_X265Encoder_paramParse != nullptr 32 | && ttLibGo_X265Encoder_paramApplyProfile != nullptr 33 | && ttLibGo_X265Encoder_makeWithX265ApiAndParam != nullptr) { 34 | uint32_t width = mp->getUint32("width"); 35 | uint32_t height = mp->getUint32("height"); 36 | string preset = mp->getString("preset"); 37 | string tune = mp->getString("tune"); 38 | string profile = mp->getString("profile"); 39 | list params = mp->getStringList("param"); 40 | void *api; 41 | void *x265Param; 42 | if(!(*ttLibGo_X265Encoder_getDefaultX265ApiAndParam)(&api, &x265Param, preset.c_str(), tune.c_str(), width, height)) { 43 | cout << "default api paramの取得に失敗しました。" << endl; 44 | return; 45 | } 46 | regex r(R"([^:]+):(.+)"); 47 | for(auto iter = params.cbegin(); iter != params.cend();++ iter) { 48 | sregex_iterator reg_iter(iter->begin(), iter->end(), r); 49 | string key = reg_iter->str(); 50 | reg_iter ++; 51 | string value = reg_iter->str(); 52 | int result = (*ttLibGo_X265Encoder_paramParse)(x265Param, key.c_str(), value.c_str()); 53 | if(result < 0) { 54 | cout << "パラメーター設定失敗:" << key << ":" << value << endl; 55 | } 56 | } 57 | if((*ttLibGo_X265Encoder_paramApplyProfile)(x265Param, profile.c_str())) { 58 | cout << "profile apply失敗しました。" << endl; 59 | _encoder = NULL; 60 | } 61 | else { 62 | _encoder = (*ttLibGo_X265Encoder_makeWithX265ApiAndParam)((void *)api, (void *)x265Param); 63 | } 64 | } 65 | } 66 | 67 | X265Encoder::~X265Encoder() { 68 | if(ttLibGo_X265Encoder_close != nullptr) { 69 | (*ttLibGo_X265Encoder_close)(&_encoder); 70 | } 71 | } 72 | bool X265Encoder::encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 73 | bool result = false; 74 | if(ttLibGo_X265Encoder_encode != nullptr) { 75 | if(cFrame->type != frameType_yuv420) { 76 | return result; 77 | } 78 | update(cFrame, goFrame); 79 | result = (*ttLibGo_X265Encoder_encode)(_encoder, cFrame, ttLibGoFrameCallback, ptr); 80 | reset(cFrame, goFrame); 81 | } 82 | return result; 83 | } 84 | 85 | bool X265Encoder::forceNextFrameType(string type) { 86 | bool result = false; 87 | if(ttLibGo_X265Encoder_forceNextFrameType != nullptr) { 88 | ttLibC_X265Encoder_FrameType frameType = X265FrameType_Auto; 89 | if(type == "I") { 90 | frameType = X265FrameType_I; 91 | } 92 | else if(type == "P") { 93 | frameType = X265FrameType_P; 94 | } 95 | else if(type == "B") { 96 | frameType = X265FrameType_B; 97 | } 98 | else if(type == "IDR") { 99 | frameType = X265FrameType_IDR; 100 | } 101 | else if(type == "Auto") { 102 | frameType = X265FrameType_Auto; 103 | } 104 | else if(type == "Bref") { 105 | frameType = X265FrameType_Bref; 106 | } 107 | else { 108 | return false; 109 | } 110 | result = (*ttLibGo_X265Encoder_forceNextFrameType)(_encoder, frameType); 111 | } 112 | return result; 113 | } 114 | 115 | extern "C" { 116 | bool X265Encoder_forceNextFrameType(void *encoder, const char *type) { 117 | X265Encoder *x = reinterpret_cast(encoder); 118 | return x->forceNextFrameType(type); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /cppsrc/encoder/x265.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_ENCODER_X265_HPP 2 | #define TTLIBGO_ENCODER_X265_HPP 3 | 4 | #include "../encoder.hpp" 5 | 6 | class X265Encoder : public Encoder { 7 | public: 8 | X265Encoder(maps *mp); 9 | ~X265Encoder(); 10 | bool encodeFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | bool forceNextFrameType(string type); 12 | private: 13 | void *_encoder; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cppsrc/frame.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_FRAME_HPP 2 | #define TTLIBGO_FRAME_HPP 3 | 4 | // goのframeが保持しているデータをコピーしておくオブジェクト 5 | class ttLibGoFrame { 6 | public: 7 | uint64_t pts; 8 | uint64_t dts; 9 | uint32_t timebase; 10 | uint32_t id; 11 | uint32_t width; 12 | uint32_t height; 13 | 14 | uint32_t sampleRate; 15 | uint32_t sampleNum; 16 | uint32_t channelNum; 17 | 18 | uint64_t dataPos; 19 | uint32_t widthStride; 20 | 21 | uint64_t yDataPos; 22 | uint32_t yStride; 23 | uint64_t uDataPos; 24 | uint32_t uStride; 25 | uint64_t vDataPos; 26 | uint32_t vStride; 27 | 28 | // pcmについては、データを参照してから、binaryを作り直すことはあっても、それを利用してデータを改変することはなさそうなので 29 | // 改変情報を保持しなくてもいいか・・・ 30 | }; 31 | 32 | class FrameProcessor { 33 | public: 34 | void update(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame); 35 | void reset(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame); 36 | private: 37 | uint64_t _pts, _dts; 38 | uint32_t _timebase; 39 | uint32_t _id; 40 | uint32_t _width, _height; 41 | uint32_t _sample_rate, _sample_num, _channel_num; 42 | uint8_t *_data, *_y_data, *_u_data, *_v_data; 43 | uint32_t _width_stride, _y_stride, _u_stride, _v_stride; 44 | }; 45 | 46 | ttLibC_Frame_Type Frame_getFrameTypeFromString(string name); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /cppsrc/reader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ttLibC/ttLibC/allocator.h" 3 | #include "ttLibC/ttLibC/container/container.h" 4 | #include 5 | 6 | using namespace std; 7 | 8 | // go側の関数をkickできるようにしておきます。 9 | extern "C" { 10 | 11 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 12 | 13 | typedef void *(* ttLibC_make_func)(); 14 | typedef bool(* ttLibC_ContainerReader_read_func)(void *, void *, size_t, bool(*)(void *, void *), void *); 15 | typedef bool(* ttLibC_Container_GetFrame_func)(void *, ttLibC_getFrameFunc, void *); 16 | typedef void (* ttLibC_close_func)(void **); 17 | 18 | extern ttLibC_make_func ttLibGo_FlvReader_make; 19 | extern ttLibC_make_func ttLibGo_MkvReader_make; 20 | extern ttLibC_make_func ttLibGo_Mp4Reader_make; 21 | extern ttLibC_make_func ttLibGo_MpegtsReader_make; 22 | 23 | extern ttLibC_ContainerReader_read_func ttLibGo_FlvReader_read; 24 | extern ttLibC_ContainerReader_read_func ttLibGo_MkvReader_read; 25 | extern ttLibC_ContainerReader_read_func ttLibGo_Mp4Reader_read; 26 | extern ttLibC_ContainerReader_read_func ttLibGo_MpegtsReader_read; 27 | 28 | extern ttLibC_Container_GetFrame_func ttLibGo_Flv_getFrame; 29 | extern ttLibC_Container_GetFrame_func ttLibGo_Mkv_getFrame; 30 | extern ttLibC_Container_GetFrame_func ttLibGo_Mp4_getFrame; 31 | extern ttLibC_Container_GetFrame_func ttLibGo_Mpegts_getFrame; 32 | 33 | extern ttLibC_close_func ttLibGo_ContainerReader_close; 34 | 35 | ttLibC_ContainerReader *ContainerReader_make(const char *format) { 36 | string fmt = string(format); 37 | if(fmt == "flv") { 38 | if(ttLibGo_FlvReader_make != nullptr) { 39 | return (ttLibC_ContainerReader *)(*ttLibGo_FlvReader_make)(); 40 | } 41 | } 42 | if(fmt == "mkv" || fmt == "webm") { 43 | if(ttLibGo_MkvReader_make != nullptr) { 44 | return (ttLibC_ContainerReader *)(*ttLibGo_MkvReader_make)(); 45 | } 46 | } 47 | if(fmt == "mp4") { 48 | if(ttLibGo_Mp4Reader_make != nullptr) { 49 | return (ttLibC_ContainerReader *)(*ttLibGo_Mp4Reader_make)(); 50 | } 51 | } 52 | if(fmt == "mpegts") { 53 | if(ttLibGo_MpegtsReader_make != nullptr) { 54 | return (ttLibC_ContainerReader *)(*ttLibGo_MpegtsReader_make)(); 55 | } 56 | } 57 | return NULL; 58 | } 59 | 60 | // 読み込み実施 61 | bool ContainerReader_read( 62 | ttLibC_ContainerReader *reader, 63 | void *data, 64 | size_t data_size, 65 | uintptr_t ptr) { 66 | if(reader == NULL) { 67 | return false; 68 | } 69 | switch(reader->type) { 70 | case containerType_flv: 71 | if(ttLibGo_FlvReader_read != nullptr) { 72 | return (*ttLibGo_FlvReader_read)(reader, data, data_size, [](void *ptr, void *flv) -> bool{ 73 | if(ttLibGo_Flv_getFrame != nullptr) { 74 | return (*ttLibGo_Flv_getFrame)(flv, ttLibGoFrameCallback, ptr); 75 | } 76 | return false; 77 | }, (void *)ptr); 78 | } 79 | break; 80 | case containerType_mkv: 81 | case containerType_webm: 82 | if(ttLibGo_MkvReader_read != nullptr) { 83 | return (*ttLibGo_MkvReader_read)(reader, data, data_size, [](void *ptr, void *mkv) -> bool{ 84 | if(ttLibGo_Mkv_getFrame != nullptr) { 85 | return (*ttLibGo_Mkv_getFrame)(mkv, ttLibGoFrameCallback, ptr); 86 | } 87 | return false; 88 | }, (void *)ptr); 89 | } 90 | break; 91 | case containerType_mp4: 92 | if(ttLibGo_Mp4Reader_read != nullptr) { 93 | return (*ttLibGo_Mp4Reader_read)(reader, data, data_size, [](void *ptr, void *mp4) -> bool{ 94 | if(ttLibGo_Mp4_getFrame != nullptr) { 95 | return (*ttLibGo_Mp4_getFrame)(mp4, ttLibGoFrameCallback, ptr); 96 | } 97 | return false; 98 | }, (void *)ptr); 99 | } 100 | break; 101 | case containerType_mpegts: 102 | if(ttLibGo_MpegtsReader_read != nullptr) { 103 | return (*ttLibGo_MpegtsReader_read)(reader, data, data_size, [](void *ptr, void *mpegts) -> bool{ 104 | if(ttLibGo_Mpegts_getFrame != nullptr) { 105 | return (*ttLibGo_Mpegts_getFrame)(mpegts, ttLibGoFrameCallback, ptr); 106 | } 107 | return false; 108 | }, (void *)ptr); 109 | } 110 | break; 111 | default: 112 | break; 113 | } 114 | return false; 115 | } 116 | 117 | void ContainerReader_close(ttLibC_ContainerReader *reader) { 118 | if(ttLibGo_ContainerReader_close != nullptr) { 119 | (*ttLibGo_ContainerReader_close)((void **)&reader); 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /cppsrc/resampler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "resampler.hpp" 5 | #include "resampler/audio.hpp" 6 | #include "resampler/image.hpp" 7 | #include "resampler/libyuv.hpp" 8 | #include "resampler/resize.hpp" 9 | #include "resampler/soundtouch.hpp" 10 | #include "resampler/speexdsp.hpp" 11 | #include "resampler/swresample.hpp" 12 | #include "resampler/swscale.hpp" 13 | #include 14 | 15 | using namespace std; 16 | 17 | Resampler *Resampler::create(maps *mp) { 18 | string resamplerType = mp->getString("resampler"); 19 | if(resamplerType == "audio") { 20 | return new AudioResampler(mp); 21 | } 22 | else if(resamplerType == "image") { 23 | return new ImageResampler(mp); 24 | } 25 | else if(resamplerType == "libyuv") { 26 | return new LibyuvResampler(mp); 27 | } 28 | else if(resamplerType == "resize") { 29 | return new ResizeResampler(mp); 30 | } 31 | else if(resamplerType == "soundtouch") { 32 | return new SoundtouchResampler(mp); 33 | } 34 | else if(resamplerType == "speexdsp") { 35 | return new SpeexdspResampler(mp); 36 | } 37 | else if(resamplerType == "swresample") { 38 | return new SwresampleResampler(mp); 39 | } 40 | else if(resamplerType == "swscale") { 41 | return new SwscaleResampler(mp); 42 | } 43 | return nullptr; 44 | } 45 | 46 | Resampler::Resampler() { 47 | } 48 | 49 | Resampler::~Resampler() { 50 | } 51 | 52 | bool Resampler::resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 53 | return false; 54 | } 55 | 56 | extern "C" { 57 | 58 | void *Resampler_make(void *mp) { 59 | maps *m = reinterpret_cast(mp); 60 | return Resampler::create(m); 61 | } 62 | bool Resampler_resampleFrame(void *resampler, void *frame, void *goFrame, uintptr_t ptr) { 63 | if(resampler == nullptr) { 64 | return false; 65 | } 66 | Resampler *r = reinterpret_cast(resampler); 67 | ttLibC_Frame *cF = reinterpret_cast(frame); 68 | ttLibGoFrame *goF = reinterpret_cast(goFrame); 69 | return r->resampleFrame(cF, goF, (void *)ptr); 70 | } 71 | 72 | void Resampler_close(void *resampler) { 73 | if(resampler == nullptr) { 74 | return; 75 | } 76 | Resampler *r = reinterpret_cast(resampler); 77 | delete r; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /cppsrc/resampler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_HPP 2 | #define TTLIBGO_RESAMPLER_HPP 3 | 4 | #include "util.hpp" 5 | #include "ttLibC/ttLibC/frame/frame.h" 6 | #include "frame.hpp" 7 | 8 | class Resampler : public FrameProcessor { 9 | public: 10 | static Resampler *create(maps *m); 11 | Resampler(); 12 | virtual ~Resampler(); 13 | virtual bool resampleFrame( 14 | ttLibC_Frame *cFrame, 15 | ttLibGoFrame *goFrame, 16 | void *ptr); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /cppsrc/resampler/audio.cpp: -------------------------------------------------------------------------------- 1 | #include "audio.hpp" 2 | #include "../util.hpp" 3 | #include "../frame.hpp" 4 | #include 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_AudioResampler_convertFormat_func)(void *, ttLibC_Frame_Type, uint32_t, uint32_t, void *); 10 | typedef void (* ttLibC_close_func)(void **); 11 | 12 | extern ttLibC_close_func ttLibGo_Frame_close; 13 | extern ttLibC_AudioResampler_convertFormat_func ttLibGo_AudioResampler_convertFormat; 14 | 15 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 16 | } 17 | 18 | uint32_t AudioResampler::getSubType(ttLibC_Frame_Type frameType, string name) { 19 | switch(frameType) { 20 | case frameType_pcmS16: 21 | if(name == "bigEndian") { 22 | return PcmS16Type_bigEndian; 23 | } 24 | else if(name == "bigEndianPlanar"){ 25 | return PcmS16Type_bigEndian_planar; 26 | } 27 | else if(name == "littleEndian"){ 28 | return PcmS16Type_littleEndian; 29 | } 30 | else if(name == "littleEndianPlanar"){ 31 | return PcmS16Type_littleEndian_planar; 32 | } 33 | break; 34 | case frameType_pcmF32: 35 | if(name == "interleave") { 36 | return PcmF32Type_interleave; 37 | } 38 | else if(name == "planar") { 39 | return PcmF32Type_planar; 40 | } 41 | break; 42 | default: 43 | break; 44 | } 45 | return 99; 46 | } 47 | 48 | AudioResampler::AudioResampler(maps *mp) { 49 | _targetType = Frame_getFrameTypeFromString(mp->getString("frameType")); 50 | _subType = getSubType(_targetType, mp->getString("subType")); 51 | _pcm = nullptr; 52 | } 53 | 54 | AudioResampler::~AudioResampler() { 55 | if(ttLibGo_Frame_close != nullptr) { 56 | (*ttLibGo_Frame_close)((void **)&_pcm); 57 | } 58 | } 59 | bool AudioResampler::resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 60 | switch(cFrame->type) { 61 | case frameType_pcmF32: 62 | case frameType_pcmS16: 63 | break; 64 | default: 65 | return false; 66 | } 67 | bool result = false; 68 | if(ttLibGo_AudioResampler_convertFormat != nullptr) { 69 | update(cFrame, goFrame); 70 | ttLibC_Audio *pcm = (ttLibC_Audio *)cFrame; 71 | ttLibC_Audio *resampled = (ttLibC_Audio *)(*ttLibGo_AudioResampler_convertFormat)(_pcm, _targetType, _subType, pcm->channel_num, pcm); 72 | if(resampled != nullptr) { 73 | _pcm = resampled; 74 | result = ttLibGoFrameCallback(ptr, (ttLibC_Frame *)_pcm); 75 | } 76 | } 77 | reset(cFrame, goFrame); 78 | return result; 79 | } 80 | -------------------------------------------------------------------------------- /cppsrc/resampler/audio.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_AUDIO_HPP 2 | #define TTLIBGO_RESAMPLER_AUDIO_HPP 3 | 4 | #include "../resampler.hpp" 5 | 6 | class AudioResampler : public Resampler { 7 | public: 8 | AudioResampler(maps *mp); 9 | ~AudioResampler(); 10 | bool resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | uint32_t getSubType(ttLibC_Frame_Type frameType, string name); 13 | ttLibC_Frame_Type _targetType; 14 | uint32_t _subType; 15 | ttLibC_Audio *_pcm; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /cppsrc/resampler/image.cpp: -------------------------------------------------------------------------------- 1 | #include "image.hpp" 2 | #include "../util.hpp" 3 | #include "../frame.hpp" 4 | #include 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef bool (* ttLibC_Resampler_convert_func)(void *, void *); 10 | extern ttLibC_Resampler_convert_func ttLibGo_ImageResampler_ToBgr; 11 | extern ttLibC_Resampler_convert_func ttLibGo_ImageResampler_ToYuv420; 12 | } 13 | 14 | ImageResampler::ImageResampler(maps *mp) { 15 | } 16 | ImageResampler::~ImageResampler() { 17 | } 18 | 19 | bool ImageResampler::toBgr( 20 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 21 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame) { 22 | bool result = false; 23 | if(ttLibGo_ImageResampler_ToBgr == nullptr) { 24 | return false; 25 | } 26 | else { 27 | update(dstCFrame, dstGoFrame); 28 | srcfp.update(srcCFrame, srcGoFrame); 29 | result = (*ttLibGo_ImageResampler_ToBgr)(dstCFrame, srcCFrame); 30 | srcfp.reset(srcCFrame, srcGoFrame); 31 | reset(dstCFrame, dstGoFrame); 32 | } 33 | return result; 34 | } 35 | 36 | bool ImageResampler::toYuv420( 37 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 38 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame) { 39 | bool result = false; 40 | if(ttLibGo_ImageResampler_ToYuv420 == nullptr) { 41 | return false; 42 | } 43 | else { 44 | update(dstCFrame, dstGoFrame); 45 | srcfp.update(srcCFrame, srcGoFrame); 46 | result = (*ttLibGo_ImageResampler_ToYuv420)(dstCFrame, srcCFrame); 47 | srcfp.reset(srcCFrame, srcGoFrame); 48 | reset(dstCFrame, dstGoFrame); 49 | } 50 | return result; 51 | } 52 | 53 | extern "C" { 54 | bool ImageResampler_toBgr( 55 | void *resampler, 56 | void *dstCFrame, void *dstGoFrame, 57 | void *srcCFrame, void *srcGoFrame) { 58 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 59 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 60 | return false; 61 | } 62 | ImageResampler *r = reinterpret_cast(resampler); 63 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 64 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 65 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 66 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 67 | return r->toBgr(dstCF, dstGoF, srcCF, srcGoF); 68 | } 69 | 70 | bool ImageResampler_toYuv420( 71 | void *resampler, 72 | void *dstCFrame, void *dstGoFrame, 73 | void *srcCFrame, void *srcGoFrame) { 74 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 75 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 76 | return false; 77 | } 78 | ImageResampler *r = reinterpret_cast(resampler); 79 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 80 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 81 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 82 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 83 | return r->toYuv420(dstCF, dstGoF, srcCF, srcGoF); 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /cppsrc/resampler/image.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_IMAGE_HPP 2 | #define TTLIBGO_RESAMPLER_IMAGE_HPP 3 | 4 | #include "../resampler.hpp" 5 | 6 | class ImageResampler : public Resampler { 7 | public: 8 | ImageResampler(maps *mp); 9 | ~ImageResampler(); 10 | // bool resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | bool toBgr( 12 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 13 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame); 14 | bool toYuv420( 15 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 16 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame); 17 | private: 18 | /* uint32_t getSubType(ttLibC_Frame_Type frameType, string name); 19 | ttLibC_Frame_Type _sourceType; 20 | 21 | ttLibC_Frame_Type _targetType; 22 | uint32_t _subType; 23 | ttLibC_Video *_image;*/ 24 | FrameProcessor srcfp; 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /cppsrc/resampler/libyuv.cpp: -------------------------------------------------------------------------------- 1 | #include "libyuv.hpp" 2 | 3 | #include "../util.hpp" 4 | #include "../frame.hpp" 5 | #include 6 | 7 | using namespace std; 8 | 9 | extern "C" { 10 | typedef bool (* ttLibC_LibyuvResampler_resize_func)(void *, void *, ttLibC_LibyuvFilter_Mode, ttLibC_LibyuvFilter_Mode); 11 | typedef bool (* ttLibC_LibyuvResampler_rotate_func)(void *, void *, ttLibC_LibyuvRotate_Mode); 12 | typedef bool (* ttLibC_Resampler_convert_func)(void *, void *); 13 | 14 | extern ttLibC_LibyuvResampler_resize_func ttLibGo_LibyuvResampler_resize; 15 | extern ttLibC_LibyuvResampler_rotate_func ttLibGo_LibyuvResampler_rotate; 16 | extern ttLibC_Resampler_convert_func ttLibGo_LibyuvResampler_ToBgr; 17 | extern ttLibC_Resampler_convert_func ttLibGo_LibyuvResampler_ToYuv420; 18 | } 19 | 20 | LibyuvResampler::LibyuvResampler(maps *mp) { 21 | } 22 | 23 | LibyuvResampler::~LibyuvResampler() { 24 | } 25 | 26 | ttLibC_LibyuvFilter_Mode LibyuvResampler::checkMode(string str) { 27 | if(str == "Linear") { 28 | return LibyuvFilter_Linear; 29 | } 30 | else if(str == "Bilinear") { 31 | return LibyuvFilter_Bilinear; 32 | } 33 | else if(str == "Box") { 34 | return LibyuvFilter_Box; 35 | } 36 | else { 37 | return LibyuvFilter_None; 38 | } 39 | } 40 | ttLibC_LibyuvRotate_Mode LibyuvResampler::checkRotate(string str) { 41 | if(str == "90") { 42 | return LibyuvRotate_90; 43 | } 44 | else if(str == "180") { 45 | return LibyuvRotate_180; 46 | } 47 | else if(str == "270") { 48 | return LibyuvRotate_270; 49 | } 50 | else { 51 | return LibyuvRotate_0; 52 | } 53 | } 54 | 55 | 56 | bool LibyuvResampler::resize( 57 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 58 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame, 59 | string strMode, 60 | string strSubMode) { 61 | bool result = false; 62 | if(ttLibGo_LibyuvResampler_resize == nullptr) { 63 | return false; 64 | } 65 | else { 66 | ttLibC_LibyuvFilter_Mode mode = checkMode(strMode); 67 | ttLibC_LibyuvFilter_Mode subMode = checkMode(strSubMode); 68 | update(dstCFrame, dstGoFrame); 69 | srcfp.update(srcCFrame, srcGoFrame); 70 | result = (*ttLibGo_LibyuvResampler_resize)(dstCFrame, srcCFrame, mode, subMode); 71 | srcfp.reset(srcCFrame, srcGoFrame); 72 | reset(dstCFrame, dstGoFrame); 73 | } 74 | return result; 75 | } 76 | 77 | bool LibyuvResampler::rotate( 78 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 79 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame, 80 | string strMode) { 81 | bool result = false; 82 | if(ttLibGo_LibyuvResampler_rotate == nullptr) { 83 | return false; 84 | } 85 | else { 86 | ttLibC_LibyuvRotate_Mode mode = checkRotate(strMode); 87 | update(dstCFrame, dstGoFrame); 88 | srcfp.update(srcCFrame, srcGoFrame); 89 | result = (*ttLibGo_LibyuvResampler_rotate)(dstCFrame, srcCFrame, mode); 90 | srcfp.reset(srcCFrame, srcGoFrame); 91 | reset(dstCFrame, dstGoFrame); 92 | } 93 | return result; 94 | } 95 | 96 | bool LibyuvResampler::toBgr( 97 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 98 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame) { 99 | bool result = false; 100 | if(ttLibGo_LibyuvResampler_ToBgr == nullptr) { 101 | return false; 102 | } 103 | else { 104 | update(dstCFrame, dstGoFrame); 105 | srcfp.update(srcCFrame, srcGoFrame); 106 | result = (*ttLibGo_LibyuvResampler_ToBgr)(dstCFrame, srcCFrame); 107 | srcfp.reset(srcCFrame, srcGoFrame); 108 | reset(dstCFrame, dstGoFrame); 109 | } 110 | return result; 111 | } 112 | 113 | bool LibyuvResampler::toYuv420( 114 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 115 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame) { 116 | bool result = false; 117 | if(ttLibGo_LibyuvResampler_ToYuv420 == nullptr) { 118 | return false; 119 | } 120 | else { 121 | update(dstCFrame, dstGoFrame); 122 | srcfp.update(srcCFrame, srcGoFrame); 123 | result = (*ttLibGo_LibyuvResampler_ToYuv420)(dstCFrame, srcCFrame); 124 | srcfp.reset(srcCFrame, srcGoFrame); 125 | reset(dstCFrame, dstGoFrame); 126 | } 127 | return result; 128 | } 129 | 130 | extern "C" { 131 | bool LibyuvResampler_resize( 132 | void *resampler, 133 | void *dstCFrame, void *dstGoFrame, 134 | void *srcCFrame, void *srcGoFrame, 135 | const char *mode, 136 | const char *sub_mode) { 137 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 138 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 139 | return false; 140 | } 141 | LibyuvResampler *r = reinterpret_cast(resampler); 142 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 143 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 144 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 145 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 146 | return r->resize(dstCF, dstGoF, srcCF, srcGoF, mode, sub_mode); 147 | } 148 | bool LibyuvResampler_rotate( 149 | void *resampler, 150 | void *dstCFrame, void *dstGoFrame, 151 | void *srcCFrame, void *srcGoFrame, 152 | const char *mode) { 153 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 154 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 155 | return false; 156 | } 157 | LibyuvResampler *r = reinterpret_cast(resampler); 158 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 159 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 160 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 161 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 162 | return r->rotate(dstCF, dstGoF, srcCF, srcGoF, mode); 163 | } 164 | 165 | bool LibyuvResampler_toBgr( 166 | void *resampler, 167 | void *dstCFrame, void *dstGoFrame, 168 | void *srcCFrame, void *srcGoFrame) { 169 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 170 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 171 | return false; 172 | } 173 | LibyuvResampler *r = reinterpret_cast(resampler); 174 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 175 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 176 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 177 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 178 | return r->toBgr(dstCF, dstGoF, srcCF, srcGoF); 179 | } 180 | 181 | bool LibyuvResampler_toYuv420( 182 | void *resampler, 183 | void *dstCFrame, void *dstGoFrame, 184 | void *srcCFrame, void *srcGoFrame) { 185 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 186 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 187 | return false; 188 | } 189 | LibyuvResampler *r = reinterpret_cast(resampler); 190 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 191 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 192 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 193 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 194 | return r->toYuv420(dstCF, dstGoF, srcCF, srcGoF); 195 | } 196 | } -------------------------------------------------------------------------------- /cppsrc/resampler/libyuv.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_LIBYUV_HPP 2 | #define TTLIBGO_RESAMPLER_LIBYUV_HPP 3 | 4 | #include "../resampler.hpp" 5 | #include "ttLibC/ttLibC/resampler/libyuvResampler.h" 6 | 7 | class LibyuvResampler : public Resampler { 8 | public: 9 | LibyuvResampler(maps *mp); 10 | ~LibyuvResampler(); 11 | bool resize( 12 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 13 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame, 14 | string mode, 15 | string subMode); 16 | bool rotate( 17 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 18 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame, 19 | string mode); 20 | bool toBgr( 21 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 22 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame); 23 | bool toYuv420( 24 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 25 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame); 26 | private: 27 | ttLibC_LibyuvFilter_Mode checkMode(string str); 28 | ttLibC_LibyuvRotate_Mode checkRotate(string str); 29 | FrameProcessor srcfp; 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /cppsrc/resampler/resize.cpp: -------------------------------------------------------------------------------- 1 | #include "resize.hpp" 2 | #include "../util.hpp" 3 | #include "../frame.hpp" 4 | #include 5 | 6 | using namespace std; 7 | 8 | extern "C" { 9 | typedef void *(* ttLibC_ImageResizer_resize_func)(void *, void *, bool); 10 | 11 | extern ttLibC_ImageResizer_resize_func ttLibGo_ImageResizer_resize; 12 | } 13 | 14 | ResizeResampler::ResizeResampler(maps *mp) { 15 | } 16 | 17 | ResizeResampler::~ResizeResampler() { 18 | } 19 | 20 | bool ResizeResampler::resize( 21 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 22 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame, 23 | bool isQuick) { 24 | bool result = false; 25 | if(ttLibGo_ImageResizer_resize == nullptr) { 26 | return false; 27 | } 28 | else { 29 | update(dstCFrame, dstGoFrame); 30 | srcfp.update(srcCFrame, srcGoFrame); 31 | result = (*ttLibGo_ImageResizer_resize)(dstCFrame, srcCFrame, isQuick); 32 | srcfp.reset(srcCFrame, srcGoFrame); 33 | reset(dstCFrame, dstGoFrame); 34 | } 35 | return result; 36 | } 37 | 38 | extern "C" { 39 | bool Resizer_resize( 40 | void *resampler, 41 | void *dstCFrame, void *dstGoFrame, 42 | void *srcCFrame, void *srcGoFrame, 43 | bool is_quick) { 44 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 45 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 46 | return false; 47 | } 48 | ResizeResampler *r = reinterpret_cast(resampler); 49 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 50 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 51 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 52 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 53 | return r->resize(dstCF, dstGoF, srcCF, srcGoF, is_quick); 54 | } 55 | } -------------------------------------------------------------------------------- /cppsrc/resampler/resize.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_RESIZE_HPP 2 | #define TTLIBGO_RESAMPLER_RESIZE_HPP 3 | 4 | #include "../resampler.hpp" 5 | 6 | class ResizeResampler : public Resampler { 7 | public: 8 | ResizeResampler(maps *mp); 9 | ~ResizeResampler(); 10 | bool resize( 11 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 12 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame, 13 | bool isQuick); 14 | private: 15 | FrameProcessor srcfp; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /cppsrc/resampler/soundtouch.cpp: -------------------------------------------------------------------------------- 1 | #include "soundtouch.hpp" 2 | #include "../util.hpp" 3 | #include 4 | 5 | using namespace std; 6 | 7 | extern "C" { 8 | typedef void *(* ttLibC_Soundtouch_make_func)(uint32_t, uint32_t); 9 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 10 | typedef void (* ttLibC_soundtouch_set_func)(void *, double); 11 | typedef void (* ttLibC_close_func)(void **); 12 | 13 | extern ttLibC_Soundtouch_make_func ttLibGo_Soundtouch_make; 14 | extern ttLibC_codec_func ttLibGo_Soundtouch_resample; 15 | extern ttLibC_close_func ttLibGo_Soundtouch_close; 16 | extern ttLibC_soundtouch_set_func ttLibGo_Soundtouch_setRate; 17 | extern ttLibC_soundtouch_set_func ttLibGo_Soundtouch_setTempo; 18 | extern ttLibC_soundtouch_set_func ttLibGo_Soundtouch_setRateChange; 19 | extern ttLibC_soundtouch_set_func ttLibGo_Soundtouch_setTempoChange; 20 | extern ttLibC_soundtouch_set_func ttLibGo_Soundtouch_setPitch; 21 | extern ttLibC_soundtouch_set_func ttLibGo_Soundtouch_setPitchOctaves; 22 | extern ttLibC_soundtouch_set_func ttLibGo_Soundtouch_setPitchSemiTones; 23 | 24 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 25 | } 26 | 27 | SoundtouchResampler::SoundtouchResampler(maps *mp) { 28 | if(ttLibGo_Soundtouch_make != nullptr) { 29 | _resampler = (* ttLibGo_Soundtouch_make)(mp->getUint32("sampleRate"), mp->getUint32("channelNum")); 30 | } 31 | } 32 | 33 | SoundtouchResampler::~SoundtouchResampler() { 34 | if(ttLibGo_Soundtouch_close != nullptr) { 35 | (*ttLibGo_Soundtouch_close)(&_resampler); 36 | } 37 | } 38 | 39 | bool SoundtouchResampler::resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 40 | bool result = false; 41 | if(ttLibGo_Soundtouch_resample != nullptr) { 42 | update(cFrame, goFrame); 43 | result = (*ttLibGo_Soundtouch_resample)(_resampler, cFrame, ttLibGoFrameCallback, ptr); 44 | reset(cFrame, goFrame); 45 | } 46 | return result; 47 | } 48 | 49 | void SoundtouchResampler::setRate(double newRate) { 50 | if(ttLibGo_Soundtouch_setRate != nullptr) { 51 | (*ttLibGo_Soundtouch_setRate)(_resampler, newRate); 52 | } 53 | } 54 | void SoundtouchResampler::setTempo(double newTempo) { 55 | if(ttLibGo_Soundtouch_setTempo != nullptr) { 56 | (*ttLibGo_Soundtouch_setTempo)(_resampler, newTempo); 57 | } 58 | } 59 | void SoundtouchResampler::setRateChange(double newRate) { 60 | if(ttLibGo_Soundtouch_setRateChange != nullptr) { 61 | (*ttLibGo_Soundtouch_setRateChange)(_resampler, newRate); 62 | } 63 | } 64 | void SoundtouchResampler::setTempoChange(double newTempo) { 65 | if(ttLibGo_Soundtouch_setTempoChange != nullptr) { 66 | (*ttLibGo_Soundtouch_setTempoChange)(_resampler, newTempo); 67 | } 68 | } 69 | void SoundtouchResampler::setPitch(double newPitch) { 70 | if(ttLibGo_Soundtouch_setPitch != nullptr) { 71 | (*ttLibGo_Soundtouch_setPitch)(_resampler, newPitch); 72 | } 73 | } 74 | void SoundtouchResampler::setPitchOctaves(double newPitch) { 75 | if(ttLibGo_Soundtouch_setPitchOctaves != nullptr) { 76 | (*ttLibGo_Soundtouch_setPitchOctaves)(_resampler, newPitch); 77 | } 78 | } 79 | void SoundtouchResampler::setPitchSemiTones(double newPitch) { 80 | if(ttLibGo_Soundtouch_setPitchSemiTones != nullptr) { 81 | (*ttLibGo_Soundtouch_setPitchSemiTones)(_resampler, newPitch); 82 | } 83 | } 84 | 85 | extern "C" { 86 | void SoundtouchResampler_setRate(void *resampler, float newRate) { 87 | SoundtouchResampler *s = reinterpret_cast(resampler); 88 | s->setRate((double)newRate); 89 | } 90 | 91 | void SoundtouchResampler_setTempo(void *resampler, float newTempo) { 92 | SoundtouchResampler *s = reinterpret_cast(resampler); 93 | s->setTempo((double)newTempo); 94 | } 95 | 96 | void SoundtouchResampler_setRateChange(void *resampler, float newRate) { 97 | SoundtouchResampler *s = reinterpret_cast(resampler); 98 | s->setRateChange((double)newRate); 99 | } 100 | 101 | void SoundtouchResampler_setTempoChange(void *resampler, float newTempo) { 102 | SoundtouchResampler *s = reinterpret_cast(resampler); 103 | s->setTempoChange((double)newTempo); 104 | } 105 | 106 | void SoundtouchResampler_setPitch(void *resampler, float newPitch) { 107 | SoundtouchResampler *s = reinterpret_cast(resampler); 108 | s->setPitch((double)newPitch); 109 | } 110 | 111 | void SoundtouchResampler_setPitchOctaves(void *resampler, float newPitch) { 112 | SoundtouchResampler *s = reinterpret_cast(resampler); 113 | s->setPitchOctaves((double)newPitch); 114 | } 115 | 116 | void SoundtouchResampler_setPitchSemiTones(void *resampler, float newPitch) { 117 | SoundtouchResampler *s = reinterpret_cast(resampler); 118 | s->setPitchSemiTones((double)newPitch); 119 | } 120 | 121 | } -------------------------------------------------------------------------------- /cppsrc/resampler/soundtouch.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_SOUNDTOUCH_HPP 2 | #define TTLIBGO_RESAMPLER_SOUNDTOUCH_HPP 3 | 4 | #include "../resampler.hpp" 5 | 6 | class SoundtouchResampler : public Resampler { 7 | public: 8 | SoundtouchResampler(maps *mp); 9 | ~SoundtouchResampler(); 10 | bool resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | // ここに追加でいろんな処理を入れておく必要があるわけか・・・ 12 | void setRate(double newRate); 13 | void setTempo(double newTempo); 14 | void setRateChange(double newRate); 15 | void setTempoChange(double newTempo); 16 | void setPitch(double newPitch); 17 | void setPitchOctaves(double newPitch); 18 | void setPitchSemiTones(double newPitch); 19 | private: 20 | void *_resampler; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /cppsrc/resampler/speexdsp.cpp: -------------------------------------------------------------------------------- 1 | #include "speexdsp.hpp" 2 | #include "../util.hpp" 3 | #include "../frame.hpp" 4 | #include 5 | #include "ttLibC/ttLibC/frame/audio/pcms16.h" 6 | 7 | using namespace std; 8 | 9 | extern "C" { 10 | typedef void *(* ttLibC_SpeexdspResampler_make_func)(uint32_t,uint32_t,uint32_t,uint32_t); 11 | typedef void *(* ttLibC_SpeexdspResampler_resample_func)(void *, void *, void *); 12 | typedef void (* ttLibC_close_func)(void **); 13 | 14 | extern ttLibC_close_func ttLibGo_Frame_close; 15 | extern ttLibC_SpeexdspResampler_make_func ttLibGo_SpeexdspResampler_make; 16 | extern ttLibC_close_func ttLibGo_SpeexdspResampler_close; 17 | extern ttLibC_SpeexdspResampler_resample_func ttLibGo_SpeexdspResampler_resample; 18 | 19 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 20 | } 21 | 22 | SpeexdspResampler::SpeexdspResampler(maps *mp) { 23 | if(ttLibGo_SpeexdspResampler_make != nullptr) { 24 | _resampler = (*ttLibGo_SpeexdspResampler_make)( 25 | mp->getUint32("channelNum"), 26 | mp->getUint32("inSampleRate"), 27 | mp->getUint32("outSampleRate"), 28 | mp->getUint32("quality")); 29 | } 30 | _pcm = nullptr; 31 | } 32 | 33 | SpeexdspResampler::~SpeexdspResampler() { 34 | if(ttLibGo_Frame_close != nullptr) { 35 | (*ttLibGo_Frame_close)((void **)&_pcm); 36 | } 37 | if(ttLibGo_SpeexdspResampler_close != nullptr) { 38 | (*ttLibGo_SpeexdspResampler_close)(&_resampler); 39 | } 40 | } 41 | bool SpeexdspResampler::resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 42 | switch(cFrame->type) { 43 | case frameType_pcmS16: 44 | break; 45 | default: 46 | return false; 47 | } 48 | bool result = false; 49 | if(ttLibGo_SpeexdspResampler_resample != nullptr) { 50 | update(cFrame, goFrame); 51 | ttLibC_PcmS16 *pcm = (ttLibC_PcmS16 *)cFrame; 52 | ttLibC_PcmS16 *resampled = (ttLibC_PcmS16 *)(*ttLibGo_SpeexdspResampler_resample)( 53 | _resampler, 54 | _pcm, 55 | pcm); 56 | if(resampled != nullptr) { 57 | _pcm = resampled; 58 | result = ttLibGoFrameCallback(ptr, (ttLibC_Frame *)_pcm); 59 | } 60 | reset(cFrame, goFrame); 61 | } 62 | return result; 63 | } 64 | -------------------------------------------------------------------------------- /cppsrc/resampler/speexdsp.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_SPEEXDSP_HPP 2 | #define TTLIBGO_RESAMPLER_SPEEXDSP_HPP 3 | 4 | #include "../resampler.hpp" 5 | 6 | class SpeexdspResampler : public Resampler { 7 | public: 8 | SpeexdspResampler(maps *mp); 9 | ~SpeexdspResampler(); 10 | bool resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | ttLibC_PcmS16 *_pcm; 13 | void *_resampler; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cppsrc/resampler/swresample.cpp: -------------------------------------------------------------------------------- 1 | #include "swresample.hpp" 2 | #include "../util.hpp" 3 | #include 4 | 5 | #include "ttLibC/ttLibC/frame/audio/pcms16.h" 6 | #include "ttLibC/ttLibC/frame/audio/pcmf32.h" 7 | 8 | using namespace std; 9 | 10 | extern "C" { 11 | typedef void *(* ttLibC_SwresampleResampler_make_func)(ttLibC_Frame_Type, uint32_t, uint32_t, uint32_t, ttLibC_Frame_Type, uint32_t, uint32_t, uint32_t); 12 | typedef void *(* ttLibC_codec_func)(void *, void *, ttLibC_getFrameFunc, void *); 13 | typedef void (* ttLibC_close_func)(void **); 14 | 15 | extern ttLibC_SwresampleResampler_make_func ttLibGo_SwresampleResampler_make; 16 | extern ttLibC_codec_func ttLibGo_SwresampleResampler_resample; 17 | extern ttLibC_close_func ttLibGo_SwresampleResampler_close; 18 | 19 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 20 | } 21 | 22 | uint32_t SwresampleResampler::getSubType(ttLibC_Frame_Type type, string name) { 23 | switch(type) { 24 | case frameType_pcmS16: 25 | if(name == "bigEndian") {return PcmS16Type_bigEndian;} 26 | if(name == "bigEndianPlanar") {return PcmS16Type_bigEndian_planar;} 27 | if(name == "littleEndian") {return PcmS16Type_littleEndian;} 28 | if(name == "littleEndianPlanar") {return PcmS16Type_littleEndian_planar;} 29 | break; 30 | case frameType_pcmF32: 31 | if(name == "interleave") {return PcmF32Type_interleave;} 32 | if(name == "planar") {return PcmF32Type_planar;} 33 | break; 34 | default: 35 | break; 36 | } 37 | return 99; 38 | } 39 | 40 | SwresampleResampler::SwresampleResampler(maps *mp) { 41 | if(ttLibGo_SwresampleResampler_make != nullptr) { 42 | ttLibC_Frame_Type inType = Frame_getFrameTypeFromString(mp->getString("inType")); 43 | uint32_t inSubType = getSubType(inType, mp->getString("inSubType")); 44 | uint32_t inSampleRate = mp->getUint32("inSampleRate"); 45 | uint32_t inChannelNum = mp->getUint32("inChannelNum"); 46 | ttLibC_Frame_Type outType = Frame_getFrameTypeFromString(mp->getString("outType")); 47 | uint32_t outSubType = getSubType(outType, mp->getString("outSubType")); 48 | uint32_t outSampleRate = mp->getUint32("outSampleRate"); 49 | uint32_t outChannelNum = mp->getUint32("outChannelNum"); 50 | _resampler = (*ttLibGo_SwresampleResampler_make)( 51 | inType, inSubType, inSampleRate, inChannelNum, 52 | outType, outSubType, outSampleRate, outChannelNum); 53 | } 54 | } 55 | 56 | SwresampleResampler::~SwresampleResampler() { 57 | if(ttLibGo_SwresampleResampler_close != nullptr) { 58 | (*ttLibGo_SwresampleResampler_close)(&_resampler); 59 | } 60 | } 61 | 62 | bool SwresampleResampler::resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr) { 63 | bool result = false; 64 | if(ttLibGo_SwresampleResampler_resample != nullptr) { 65 | update(cFrame, goFrame); 66 | result = (*ttLibGo_SwresampleResampler_resample)( 67 | _resampler, 68 | cFrame, 69 | ttLibGoFrameCallback, 70 | ptr); 71 | reset(cFrame, goFrame); 72 | } 73 | return result; 74 | } 75 | -------------------------------------------------------------------------------- /cppsrc/resampler/swresample.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_SWRESAMPLE_HPP 2 | #define TTLIBGO_RESAMPLER_SWRESAMPLE_HPP 3 | 4 | #include "../resampler.hpp" 5 | 6 | class SwresampleResampler : public Resampler { 7 | public: 8 | SwresampleResampler(maps *mp); 9 | ~SwresampleResampler(); 10 | bool resampleFrame(ttLibC_Frame *cFrame, ttLibGoFrame *goFrame, void *ptr); 11 | private: 12 | uint32_t getSubType(ttLibC_Frame_Type type, string name); 13 | void *_resampler; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /cppsrc/resampler/swscale.cpp: -------------------------------------------------------------------------------- 1 | #include "swscale.hpp" 2 | #include "../util.hpp" 3 | #include 4 | 5 | #include "ttLibC/ttLibC/frame/video/bgr.h" 6 | #include "ttLibC/ttLibC/frame/video/yuv420.h" 7 | #include "ttLibC/ttLibC/resampler/swscaleResampler.h" 8 | 9 | using namespace std; 10 | 11 | extern "C" { 12 | typedef void *(* ttLibC_SwscaleResampler_make_func)(ttLibC_Frame_Type, uint32_t, uint32_t, uint32_t, ttLibC_Frame_Type, uint32_t, uint32_t, uint32_t, ttLibC_SwscaleResampler_Mode); 13 | typedef void *(* ttLibC_SwscaleResampler_resample_func)(void *, void *, void *); 14 | typedef void (* ttLibC_close_func)(void **); 15 | 16 | extern ttLibC_SwscaleResampler_make_func ttLibGo_SwscaleResampler_make; 17 | extern ttLibC_SwscaleResampler_resample_func ttLibGo_SwscaleResampler_resample; 18 | extern ttLibC_close_func ttLibGo_SwscaleResampler_close; 19 | 20 | extern bool ttLibGoFrameCallback(void *ptr, ttLibC_Frame *frame); 21 | } 22 | 23 | uint32_t SwscaleResampler::getSubType(ttLibC_Frame_Type type, string name) { 24 | switch(type) { 25 | case frameType_bgr: 26 | if(name == "bgr") {return BgrType_bgr;} 27 | if(name == "rgb") {return BgrType_rgb;} 28 | if(name == "abgr") {return BgrType_abgr;} 29 | if(name == "argb") {return BgrType_argb;} 30 | if(name == "bgra") {return BgrType_bgra;} 31 | if(name == "rgba") {return BgrType_rgba;} 32 | break; 33 | case frameType_yuv420: 34 | if(name == "yuv420") {return Yuv420Type_planar;} 35 | if(name == "yuv420SemiPlanar") {return Yuv420Type_semiPlanar;} 36 | if(name == "yvu420") {return Yvu420Type_planar;} 37 | if(name == "yvu420SemiPlanar") {return Yvu420Type_semiPlanar;} 38 | break; 39 | default: 40 | break; 41 | } 42 | return 99; 43 | } 44 | 45 | SwscaleResampler::SwscaleResampler(maps *mp) { 46 | if(ttLibGo_SwscaleResampler_make != nullptr) { 47 | ttLibC_Frame_Type inType = Frame_getFrameTypeFromString(mp->getString("inType")); 48 | uint32_t inSubType = getSubType(inType, mp->getString("inSubType")); 49 | uint32_t inWidth = mp->getUint32("inWidth"); 50 | uint32_t inHeight = mp->getUint32("inHeight"); 51 | ttLibC_Frame_Type outType = Frame_getFrameTypeFromString(mp->getString("outType")); 52 | uint32_t outSubType = getSubType(outType, mp->getString("outSubType")); 53 | uint32_t outWidth = mp->getUint32("outWidth"); 54 | uint32_t outHeight = mp->getUint32("outHeight"); 55 | string mode = mp->getString("mode"); 56 | ttLibC_SwscaleResampler_Mode scaleMode = SwscaleResampler_FastBiLinear; 57 | if(mode == "X") { 58 | scaleMode = SwscaleResampler_X; 59 | } 60 | else if(mode == "Area") { 61 | scaleMode = SwscaleResampler_Area; 62 | } 63 | else if(mode == "Sinc") { 64 | scaleMode = SwscaleResampler_Sinc; 65 | } 66 | else if(mode == "Point") { 67 | scaleMode = SwscaleResampler_Point; 68 | } 69 | else if(mode == "Gauss") { 70 | scaleMode = SwscaleResampler_Gauss; 71 | } 72 | else if(mode == "Spline") { 73 | scaleMode = SwscaleResampler_Spline; 74 | } 75 | else if(mode == "Bicubic") { 76 | scaleMode = SwscaleResampler_Bicubic; 77 | } 78 | else if(mode == "Lanczos") { 79 | scaleMode = SwscaleResampler_Lanczos; 80 | } 81 | else if(mode == "Bilinear") { 82 | scaleMode = SwscaleResampler_Bilinear; 83 | } 84 | else if(mode == "Bicublin") { 85 | scaleMode = SwscaleResampler_Bicublin; 86 | } 87 | else if(mode == "FastBilinear") { 88 | scaleMode = SwscaleResampler_FastBiLinear; 89 | } 90 | _resampler = (*ttLibGo_SwscaleResampler_make)( 91 | inType, inSubType, inWidth, inHeight, 92 | outType, outSubType, outWidth, outHeight, 93 | scaleMode 94 | ); 95 | } 96 | } 97 | 98 | SwscaleResampler::~SwscaleResampler() { 99 | if(ttLibGo_SwscaleResampler_close != nullptr) { 100 | (* ttLibGo_SwscaleResampler_close)(&_resampler); 101 | } 102 | } 103 | bool SwscaleResampler::resample( 104 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 105 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame) { 106 | bool result = false; 107 | if(ttLibGo_SwscaleResampler_resample == nullptr) { 108 | return false; 109 | } 110 | else { 111 | update(dstCFrame, dstGoFrame); 112 | srcfp.update(srcCFrame, srcGoFrame); 113 | result = (*ttLibGo_SwscaleResampler_resample)(_resampler, dstCFrame, srcCFrame); 114 | srcfp.reset(srcCFrame, srcGoFrame); 115 | reset(dstCFrame, dstGoFrame); 116 | } 117 | return result; 118 | } 119 | 120 | extern "C" { 121 | bool SwscaleResampler_resample(void *resampler, 122 | void *dstCFrame, void *dstGoFrame, 123 | void *srcCFrame, void *srcGoFrame) { 124 | if(resampler == nullptr || dstCFrame == nullptr || dstGoFrame == nullptr 125 | || srcCFrame == nullptr || srcGoFrame == nullptr) { 126 | return false; 127 | } 128 | SwscaleResampler *r = reinterpret_cast(resampler); 129 | ttLibC_Frame *dstCF = reinterpret_cast(dstCFrame); 130 | ttLibGoFrame *dstGoF = reinterpret_cast(dstGoFrame); 131 | ttLibC_Frame *srcCF = reinterpret_cast(srcCFrame); 132 | ttLibGoFrame *srcGoF = reinterpret_cast(srcGoFrame); 133 | return r->resample(dstCF, dstGoF, srcCF, srcGoF); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /cppsrc/resampler/swscale.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_RESAMPLER_SWSCALE_HPP 2 | #define TTLIBGO_RESAMPLER_SWSCALE_HPP 3 | 4 | #include "../resampler.hpp" 5 | 6 | class SwscaleResampler : public Resampler { 7 | public: 8 | SwscaleResampler(maps *mp); 9 | ~SwscaleResampler(); 10 | bool resample( 11 | ttLibC_Frame *dstCFrame, ttLibGoFrame *dstGoFrame, 12 | ttLibC_Frame *srcCFrame, ttLibGoFrame *srcGoFrame); 13 | private: 14 | uint32_t getSubType(ttLibC_Frame_Type type, string name); 15 | void *_resampler; 16 | FrameProcessor srcfp; 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /cppsrc/util.cpp: -------------------------------------------------------------------------------- 1 | //#include "ttLibC/ttLibC/util/stlMapUtil.h" 2 | #include 3 | #include 4 | #include "util.hpp" 5 | 6 | using namespace std; 7 | 8 | string maps::getString(string key) { 9 | auto iter = strmap.find(key); 10 | if(iter != strmap.end()) { 11 | return iter->second; 12 | } 13 | return ""; 14 | } 15 | uint32_t maps::getUint32(string key) { 16 | auto iter = uint32map.find(key); 17 | if(iter != uint32map.end()) { 18 | return iter->second; 19 | } 20 | return 0; 21 | } 22 | uint64_t maps::getUint64(string key) { 23 | auto iter = uint64map.find(key); 24 | if(iter != uint64map.end()) { 25 | return iter->second; 26 | } 27 | return 0; 28 | } 29 | list maps::getStringList(string key) { 30 | auto iter = strlistmap.find(key); 31 | if(iter != strlistmap.end()) { 32 | return iter->second; 33 | } 34 | list empty; 35 | return empty; 36 | } 37 | 38 | extern "C" { 39 | 40 | // string -> stringで持っておいて、数値だったら、castするか・・・ 41 | void *StdMap_make() { 42 | maps *m = new maps(); 43 | return (void *)m; 44 | } 45 | void StdMap_putString(void *ptr, const char *key, const char *value) { 46 | maps *m = reinterpret_cast(ptr); 47 | m->strmap.insert(pair(key, value)); 48 | } 49 | void StdMap_putUint32(void *ptr, const char *key, uint32_t value) { 50 | maps *m = reinterpret_cast(ptr); 51 | m->uint32map.insert(pair(key, value)); 52 | } 53 | void StdMap_putUint64(void *ptr, const char *key, uint64_t value) { 54 | maps *m = reinterpret_cast(ptr); 55 | m->uint64map.insert(pair(key, value)); 56 | } 57 | 58 | void StdMap_putStringList(void *ptr, const char *key, const char *value) { 59 | maps *m = reinterpret_cast(ptr); 60 | auto iter = m->strlistmap.find(key); 61 | if(iter == m->strlistmap.end()) { 62 | // データがないので、作らなければならない。 63 | list newList; 64 | newList.push_back(value); 65 | m->strlistmap.insert(pair>(key, newList)); 66 | } 67 | else { 68 | list l = iter->second; 69 | l.push_back(value); 70 | m->strlistmap.erase(key); 71 | m->strlistmap.insert(pair>(key, l)); 72 | } 73 | } 74 | 75 | void StdMap_close(void *ptr) { 76 | maps *m = reinterpret_cast(ptr); 77 | delete m; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /cppsrc/util.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TTLIBGO_UTIL_HPP 2 | #define TTLIBGO_UTIL_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | class maps { 10 | public: 11 | map strmap; 12 | map uint32map; 13 | map uint64map; 14 | map> strlistmap; 15 | 16 | string getString(string key); 17 | uint32_t getUint32(string key); 18 | uint64_t getUint64(string key); 19 | list getStringList(string key); 20 | }; 21 | 22 | #endif -------------------------------------------------------------------------------- /cppsrc/writer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "util.hpp" 3 | #include "ttLibC/ttLibC/container/container.h" 4 | #include "ttLibC/ttLibC/container/flv.h" 5 | #include "ttLibC/ttLibC/container/mp4.h" 6 | #include "ttLibC/ttLibC/container/mkv.h" 7 | #include "ttLibC/ttLibC/container/mpegts.h" 8 | #include "ttLibC/ttLibC/container/containerCommon.h" 9 | #include "frame.hpp" 10 | 11 | extern "C" { 12 | typedef void *(* ttLibC_FlvWriter_make_func)(ttLibC_Frame_Type, ttLibC_Frame_Type); 13 | typedef void *(* ttLibC_containerWriter_make_func)(ttLibC_Frame_Type *, uint32_t); 14 | typedef bool (* ttLibC_containerWriter_write_func)(void *, void *, bool(*)(void *, void *, size_t), void *); 15 | typedef bool (* ttLibC_mpegtsWriter_writeInfo_func)(void *, bool(*)(void *, void *,size_t), void *); 16 | typedef void (* ttLibC_close_func)(void **); 17 | 18 | extern ttLibC_FlvWriter_make_func ttLibGo_FlvWriter_make; 19 | extern ttLibC_containerWriter_make_func ttLibGo_Mp4Writer_make; 20 | extern ttLibC_containerWriter_make_func ttLibGo_MpegtsWriter_make; 21 | extern ttLibC_containerWriter_make_func ttLibGo_MkvWriter_make; 22 | extern ttLibC_containerWriter_write_func ttLibGo_FlvWriter_write; 23 | extern ttLibC_containerWriter_write_func ttLibGo_MkvWriter_write; 24 | extern ttLibC_containerWriter_write_func ttLibGo_Mp4Writer_write; 25 | extern ttLibC_containerWriter_write_func ttLibGo_MpegtsWriter_write; 26 | extern ttLibC_mpegtsWriter_writeInfo_func ttLibGo_MpegtsWriter_writeInfo; 27 | extern ttLibC_close_func ttLibGo_ContainerWriter_close; 28 | 29 | extern bool ttLibGoDataCallback(void *ptr, void *data, size_t data_size); 30 | } 31 | 32 | class Writer : public FrameProcessor { 33 | public: 34 | Writer(maps *m) { 35 | if(ttLibGo_FlvWriter_make != nullptr 36 | && ttLibGo_Mp4Writer_make != nullptr 37 | && ttLibGo_MpegtsWriter_make != nullptr 38 | && ttLibGo_MkvWriter_make != nullptr) { 39 | string type = m->getString("type"); 40 | if(type == "flv") { 41 | _writer = (ttLibC_ContainerWriter *)(*ttLibGo_FlvWriter_make)( 42 | Frame_getFrameTypeFromString(m->getString("videoType")), 43 | Frame_getFrameTypeFromString(m->getString("audioType"))); 44 | return; 45 | } 46 | list frameList = m->getStringList("frameTypes"); 47 | ttLibC_Frame_Type *types = new ttLibC_Frame_Type[frameList.size()]; 48 | int i = 0; 49 | for(auto iter = frameList.cbegin(); iter != frameList.cend(); ++ iter) { 50 | types[i] = Frame_getFrameTypeFromString(*iter); 51 | i ++; 52 | } 53 | if(type == "mp4") { 54 | _writer = (ttLibC_ContainerWriter *)(*ttLibGo_Mp4Writer_make)(types, frameList.size()); 55 | } 56 | else if(type == "mpegts") { 57 | _writer = (ttLibC_ContainerWriter *)(*ttLibGo_MpegtsWriter_make)(types, frameList.size()); 58 | } 59 | else if(type == "mkv") { 60 | _writer = (ttLibC_ContainerWriter *)(*ttLibGo_MkvWriter_make)(types, frameList.size()); 61 | } 62 | else if(type == "webm") { 63 | _writer = (ttLibC_ContainerWriter *)(*ttLibGo_MkvWriter_make)(types, frameList.size()); 64 | _writer->type = containerType_webm; 65 | } 66 | delete[] types; 67 | } 68 | } 69 | ~Writer() { 70 | if(ttLibGo_ContainerWriter_close != nullptr) { 71 | (*ttLibGo_ContainerWriter_close)((void **)&_writer); 72 | } 73 | } 74 | bool writeFrame( 75 | ttLibC_Frame *cFrame, 76 | ttLibGoFrame *goFrame, 77 | uint32_t mode, 78 | uint32_t unitDuration, 79 | void *ptr) { 80 | if(_writer == nullptr) { 81 | return false; 82 | } 83 | bool result = false; 84 | if(ttLibGo_FlvWriter_write != nullptr 85 | && ttLibGo_MkvWriter_write != nullptr 86 | && ttLibGo_MpegtsWriter_write != nullptr 87 | && ttLibGo_Mp4Writer_write != nullptr) { 88 | update(cFrame, goFrame); 89 | _writer->mode = mode; 90 | switch(_writer->type) { 91 | case containerType_flv: 92 | result = (*ttLibGo_FlvWriter_write)((ttLibC_FlvWriter *)_writer, cFrame, ttLibGoDataCallback, (void *)ptr); 93 | break; 94 | case containerType_mkv: 95 | case containerType_webm: 96 | ((ttLibC_ContainerWriter_ *)_writer)->unit_duration = unitDuration; 97 | result = (*ttLibGo_MkvWriter_write)((ttLibC_MkvWriter *)_writer, cFrame, ttLibGoDataCallback, (void *)ptr); 98 | break; 99 | case containerType_mp4: 100 | ((ttLibC_ContainerWriter_ *)_writer)->unit_duration = unitDuration; 101 | result = (*ttLibGo_Mp4Writer_write)((ttLibC_Mp4Writer *)_writer, cFrame, ttLibGoDataCallback, (void *)ptr); 102 | break; 103 | case containerType_mpegts: 104 | ((ttLibC_ContainerWriter_ *)_writer)->unit_duration = unitDuration; 105 | result = (*ttLibGo_MpegtsWriter_write)((ttLibC_MpegtsWriter *)_writer, cFrame, ttLibGoDataCallback, (void *)ptr); 106 | break; 107 | default: 108 | break; 109 | } 110 | reset(cFrame, goFrame); 111 | } 112 | return result; 113 | } 114 | bool writeInfo(void *ptr) { 115 | if(_writer == NULL) { 116 | return false; 117 | } 118 | if(_writer->type != containerType_mpegts) { 119 | return true; 120 | } 121 | if(ttLibGo_MpegtsWriter_writeInfo != nullptr) { 122 | return (*ttLibGo_MpegtsWriter_writeInfo)((ttLibC_MpegtsWriter *)_writer, ttLibGoDataCallback, (void *)ptr); 123 | } 124 | return false; 125 | } 126 | uint64_t getPts() { 127 | if(_writer == nullptr) { 128 | return 0; 129 | } 130 | return _writer->pts; 131 | } 132 | uint32_t getTimebase() { 133 | if(_writer == nullptr) { 134 | return 1000; 135 | } 136 | return _writer->timebase; 137 | } 138 | private: 139 | ttLibC_ContainerWriter *_writer; 140 | }; 141 | 142 | extern "C" { 143 | 144 | void *ContainerWriter_make(void *mp) { 145 | // これでmapの情報から、初期化を実施すれば良い。 146 | maps *m = reinterpret_cast(mp); 147 | return new Writer(m); 148 | } 149 | bool ContainerWriter_writeFrame(void *writer, void *frame, void *goFrame, uint32_t mode, uint32_t unitDuration, uintptr_t ptr) { 150 | if(writer == nullptr) { 151 | return false; 152 | } 153 | Writer *w = reinterpret_cast(writer); 154 | ttLibC_Frame *cF = reinterpret_cast(frame); 155 | ttLibGoFrame *goF = reinterpret_cast(goFrame); 156 | return w->writeFrame(cF, goF, mode, unitDuration, (void *)ptr); 157 | } 158 | bool ContainerWriter_writeInfo(void *writer, uintptr_t ptr) { 159 | if(writer == nullptr) { 160 | return false; 161 | } 162 | Writer *w = reinterpret_cast(writer); 163 | return w->writeInfo((void *)ptr); 164 | } 165 | void ContainerWriter_close(void *writer) { 166 | Writer *w = reinterpret_cast(writer); 167 | delete w; 168 | } 169 | 170 | uint64_t ContainerWriter_getPts(void *writer) { 171 | Writer *w = reinterpret_cast(writer); 172 | return w->getPts(); 173 | } 174 | 175 | uint32_t ContainerWriter_getTimebase(void *writer) { 176 | Writer *w = reinterpret_cast(writer); 177 | return w->getTimebase(); 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /decoder.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | 8 | extern void *Decoder_make(void *mp); 9 | extern bool Decoder_decodeFrame(void *decoder, void *frame, void *classFrame, uintptr_t ptr); 10 | extern void Decoder_close(void *decoder); 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | // cttLibCDecoder c言語のdecoder 18 | type cttLibCDecoder unsafe.Pointer 19 | 20 | // decoderType decoderタイプ 21 | type decoderType struct{ value string } 22 | 23 | // IDecoder デコーダー 24 | type IDecoder interface { 25 | DecodeFrame( 26 | frame IFrame, 27 | callback func(frame *Frame) bool) bool 28 | Close() 29 | } 30 | 31 | // dsecoder デコーダー 32 | type decoder struct { 33 | Type decoderType 34 | cDecoder cttLibCDecoder 35 | call frameCall 36 | } 37 | 38 | // DecoderTypes Decoderタイプリスト 39 | var DecoderTypes = struct { 40 | AvcodecVideo decoderType 41 | AvcodecAudio decoderType 42 | Jpeg decoderType 43 | Openh264 decoderType 44 | Opus decoderType 45 | Png decoderType 46 | Speex decoderType 47 | Theora decoderType 48 | Vorbis decoderType 49 | }{ 50 | decoderType{"avcodecVideo"}, 51 | decoderType{"avcodecAudio"}, 52 | decoderType{"jpeg"}, 53 | decoderType{"openh264"}, 54 | decoderType{"opus"}, 55 | decoderType{"png"}, 56 | decoderType{"speex"}, 57 | decoderType{"theora"}, 58 | decoderType{"vorbis"}, 59 | } 60 | 61 | // Decoders Decoder作成 62 | var Decoders = struct { 63 | AvcodecVideo func(frameType frameType, width uint32, height uint32) *decoder 64 | AvcodecAudio func(frameType frameType, sampleRate uint32, channelNum uint32) *decoder 65 | Jpeg func() *decoder 66 | Openh264 func() *decoder 67 | Opus func(sampleRate uint32, channelNum uint32) *opusDecoder 68 | Png func() *decoder 69 | Speex func(sampleRate uint32, channelNum uint32) *decoder 70 | Theora func() *decoder 71 | Vorbis func() *decoder 72 | }{ 73 | AvcodecVideo: func(frameType frameType, width uint32, height uint32) *decoder { 74 | decoder := new(decoder) 75 | decoder.Type = DecoderTypes.AvcodecVideo 76 | params := map[string]interface{}{ 77 | "decoder": decoder.Type.value, 78 | "frameType": frameType.value, 79 | "width": width, 80 | "height": height, 81 | } 82 | v := mapUtil.fromMap(params) 83 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 84 | mapUtil.close(v) 85 | return decoder 86 | }, 87 | AvcodecAudio: func(frameType frameType, sampleRate uint32, channelNum uint32) *decoder { 88 | decoder := new(decoder) 89 | decoder.Type = DecoderTypes.AvcodecAudio 90 | params := map[string]interface{}{ 91 | "decoder": decoder.Type.value, 92 | "frameType": frameType.value, 93 | "sampleRate": sampleRate, 94 | "channelNum": channelNum, 95 | } 96 | v := mapUtil.fromMap(params) 97 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 98 | mapUtil.close(v) 99 | return decoder 100 | }, 101 | Jpeg: func() *decoder { 102 | decoder := new(decoder) 103 | decoder.Type = DecoderTypes.Jpeg 104 | params := map[string]interface{}{ 105 | "decoder": decoder.Type.value, 106 | } 107 | v := mapUtil.fromMap(params) 108 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 109 | mapUtil.close(v) 110 | return decoder 111 | }, 112 | Openh264: func() *decoder { 113 | decoder := new(decoder) 114 | decoder.Type = DecoderTypes.Openh264 115 | params := map[string]interface{}{ 116 | "decoder": decoder.Type.value, 117 | } 118 | v := mapUtil.fromMap(params) 119 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 120 | mapUtil.close(v) 121 | return decoder 122 | }, 123 | Opus: func(sampleRate uint32, channelNum uint32) *opusDecoder { 124 | decoder := new(opusDecoder) 125 | decoder.Type = DecoderTypes.Opus 126 | params := map[string]interface{}{ 127 | "decoder": decoder.Type.value, 128 | "sampleRate": sampleRate, 129 | "channelNum": channelNum, 130 | } 131 | v := mapUtil.fromMap(params) 132 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 133 | mapUtil.close(v) 134 | return decoder 135 | }, 136 | Png: func() *decoder { 137 | decoder := new(decoder) 138 | decoder.Type = DecoderTypes.Png 139 | params := map[string]interface{}{ 140 | "decoder": decoder.Type.value, 141 | } 142 | v := mapUtil.fromMap(params) 143 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 144 | mapUtil.close(v) 145 | return decoder 146 | }, 147 | Speex: func(sampleRate uint32, channelNum uint32) *decoder { 148 | decoder := new(decoder) 149 | decoder.Type = DecoderTypes.Speex 150 | params := map[string]interface{}{ 151 | "decoder": decoder.Type.value, 152 | "sampleRate": sampleRate, 153 | "channelNum": channelNum, 154 | } 155 | v := mapUtil.fromMap(params) 156 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 157 | mapUtil.close(v) 158 | return decoder 159 | }, 160 | Theora: func() *decoder { 161 | decoder := new(decoder) 162 | decoder.Type = DecoderTypes.Theora 163 | params := map[string]interface{}{ 164 | "decoder": decoder.Type.value, 165 | } 166 | v := mapUtil.fromMap(params) 167 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 168 | mapUtil.close(v) 169 | return decoder 170 | }, 171 | Vorbis: func() *decoder { 172 | decoder := new(decoder) 173 | decoder.Type = DecoderTypes.Vorbis 174 | params := map[string]interface{}{ 175 | "decoder": decoder.Type.value, 176 | } 177 | v := mapUtil.fromMap(params) 178 | decoder.cDecoder = cttLibCDecoder(C.Decoder_make(v)) 179 | mapUtil.close(v) 180 | return decoder 181 | }, 182 | } 183 | 184 | func decoderDecodeFrame( 185 | decoder *decoder, 186 | frame IFrame, 187 | callback func(frame *Frame) bool) bool { 188 | if decoder.cDecoder == nil { 189 | return false 190 | } 191 | if frame == nil { 192 | return true 193 | } 194 | cframe := frame.newGoRefFrame() 195 | decoder.call.callback = callback 196 | result := C.Decoder_decodeFrame( 197 | unsafe.Pointer(decoder.cDecoder), 198 | unsafe.Pointer(frame.refCFrame()), 199 | cframe, 200 | C.uintptr_t(uintptr(unsafe.Pointer(&decoder.call)))) 201 | frame.deleteGoRefFrame(cframe) 202 | return bool(result) 203 | } 204 | 205 | func decoderClose(decoder *decoder) { 206 | C.Decoder_close(unsafe.Pointer(decoder.cDecoder)) 207 | } 208 | 209 | // DecodeFrame デコードを実行 210 | func (decoder *decoder) DecodeFrame( 211 | frame IFrame, 212 | callback func(frame *Frame) bool) bool { 213 | return decoderDecodeFrame(decoder, frame, callback) 214 | } 215 | 216 | // Close 閉じる 217 | func (decoder *decoder) Close() { 218 | decoderClose(decoder) 219 | } 220 | -------------------------------------------------------------------------------- /decoderOpus.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | extern int OpusDecoder_codecControl(void *ptr, const char *key, int value); 7 | */ 8 | import "C" 9 | import ( 10 | "reflect" 11 | "unsafe" 12 | ) 13 | 14 | type opusDecoder decoder 15 | 16 | // OpusDecoderControls codecControlで設定可能な項目 17 | var OpusDecoderControls = struct { 18 | ResetState subType 19 | GetFinalRange subType 20 | GetBandwidth subType 21 | GetSampleRate subType 22 | SetPhaseInversionDisabled subType 23 | GetPhaseInversionDisabled subType 24 | SetGain subType 25 | GetGain subType 26 | GetLastPacketDuration subType 27 | GetPitch subType 28 | }{ 29 | subType{"OPUS_RESET_STATE"}, 30 | subType{"OPUS_GET_FINAL_RANGE"}, 31 | subType{"OPUS_GET_BANDWIDTH"}, 32 | subType{"OPUS_GET_SAMPLE_RATE"}, 33 | subType{"OPUS_SET_PHASE_INVERSION_DISABLED"}, 34 | subType{"OPUS_GET_PHASE_INVERSION_DISABLED"}, 35 | subType{"OPUS_SET_GAIN"}, 36 | subType{"OPUS_GET_GAIN"}, 37 | subType{"OPUS_GET_LAST_PACKET_DURATION"}, 38 | subType{"OPUS_GET_PITCH"}, 39 | } 40 | 41 | // DecodeFrame デコードを実行 42 | func (opusDecoder *opusDecoder) DecodeFrame( 43 | frame IFrame, 44 | callback func(frame *Frame) bool) bool { 45 | return decoderDecodeFrame((*decoder)(opusDecoder), frame, callback) 46 | } 47 | 48 | // Close 閉じる 49 | func (opusDecoder *opusDecoder) Close() { 50 | decoderClose((*decoder)(opusDecoder)) 51 | } 52 | 53 | // SetCodecControl 追加パラメーター設定 54 | func (opusDecoder *opusDecoder) SetCodecControl(control subType, value interface{}) { 55 | ckey := C.CString(control.value) 56 | defer C.free(unsafe.Pointer(ckey)) 57 | // valueについて、reflectでなんとかしなければならない 58 | ivalue := 0 59 | switch reflect.TypeOf(value).Kind() { 60 | case reflect.Uint32: 61 | ivalue = int(value.(uint32)) 62 | case reflect.Int: 63 | ivalue = value.(int) 64 | case reflect.Int32: 65 | ivalue = int(value.(int32)) 66 | case reflect.Bool: 67 | if value.(bool) { 68 | ivalue = 1 69 | } 70 | } 71 | C.OpusDecoder_codecControl(unsafe.Pointer(opusDecoder.cDecoder), ckey, C.int(ivalue)) 72 | } 73 | 74 | // GetCodecControl 追加パラメーター参照 75 | func (opusDecoder *opusDecoder) GetCodecControl(control subType) int32 { 76 | ckey := C.CString(control.value) 77 | defer C.free(unsafe.Pointer(ckey)) 78 | return int32(C.OpusDecoder_codecControl(unsafe.Pointer(opusDecoder.cDecoder), ckey, C.int(0))) 79 | } 80 | -------------------------------------------------------------------------------- /encoderFdkaac.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | extern bool FdkaacEncoder_setBitrate(void *ptr, uint32_t value); 8 | */ 9 | import "C" 10 | import ( 11 | "unsafe" 12 | ) 13 | 14 | type fdkaacEncoder encoder 15 | 16 | // FdkAacTypes fdkaacEncoderで利用できる動作タイプ 17 | var FdkAacTypes = struct { 18 | AotNone subType 19 | AotNullObject subType 20 | AotAacMAIN subType 21 | AotAacLC subType 22 | AotAacSSR subType 23 | AotAacLTP subType 24 | AotSBR subType 25 | AotAacSCAL subType 26 | AotTwinVQ subType 27 | AotCELP subType 28 | AotHVXC subType 29 | AotRsvd10 subType 30 | AotRsvd11 subType 31 | AotTTSI subType 32 | AotMainSYNTH subType 33 | AotWavTabSYNTH subType 34 | AotGenMIDI subType 35 | AotAlgSynthAudFX subType 36 | AotErAacLC subType 37 | AotRsvd18 subType 38 | AotErAacLTP subType 39 | AotErAacSCAL subType 40 | AotErTwinVQ subType 41 | AotErBSAC subType 42 | AotErAacLD subType 43 | AotErCELP subType 44 | AotErHVXC subType 45 | AotErHILN subType 46 | AotErPARA subType 47 | AotRsvd28 subType 48 | AotPS subType 49 | AotMPEGS subType 50 | AotESCAPE subType 51 | AotMp3onMp4L1 subType 52 | AotMp3onMp4L2 subType 53 | AotMp3onMp4L3 subType 54 | AotRsvd35 subType 55 | AotRsvd36 subType 56 | AotAacSLS subType 57 | AotSLS subType 58 | AotErAacELD subType 59 | AotUSAC subType 60 | AotSAOC subType 61 | AotLdMPEGS subType 62 | AotDrmAAC subType 63 | AotDrmSBR subType 64 | AotDrmMpegPS subType 65 | }{ 66 | AotNone: subType{"AOT_NONE"}, 67 | AotNullObject: subType{"AOT_NULL_OBJECT"}, 68 | AotAacMAIN: subType{"AOT_AAC_MAIN"}, 69 | AotAacLC: subType{"AOT_AAC_LC"}, 70 | AotAacSSR: subType{"AOT_AAC_SSR"}, 71 | AotAacLTP: subType{"AOT_AAC_LTP"}, 72 | AotSBR: subType{"AOT_SBR"}, 73 | AotAacSCAL: subType{"AOT_AAC_SCAL"}, 74 | AotTwinVQ: subType{"AOT_TWIN_VQ"}, 75 | AotCELP: subType{"AOT_CELP"}, 76 | AotHVXC: subType{"AOT_HVXC"}, 77 | AotRsvd10: subType{"AOT_RSVD_10"}, 78 | AotRsvd11: subType{"AOT_RSVD_11"}, 79 | AotTTSI: subType{"AOT_TTSI"}, 80 | AotMainSYNTH: subType{"AOT_MAIN_SYNTH"}, 81 | AotWavTabSYNTH: subType{"AOT_WAV_TAB_SYNTH"}, 82 | AotGenMIDI: subType{"AOT_GEN_MIDI"}, 83 | AotAlgSynthAudFX: subType{"AOT_ALG_SYNTH_AUD_FX"}, 84 | AotErAacLC: subType{"AOT_ER_AAC_LC"}, 85 | AotRsvd18: subType{"AOT_RSVD_18"}, 86 | AotErAacLTP: subType{"AOT_ER_AAC_LTP"}, 87 | AotErAacSCAL: subType{"AOT_ER_AAC_SCAL"}, 88 | AotErTwinVQ: subType{"AOT_ER_TWIN_VQ"}, 89 | AotErBSAC: subType{"AOT_ER_BSAC"}, 90 | AotErAacLD: subType{"AOT_ER_AAC_LD"}, 91 | AotErCELP: subType{"AOT_ER_CELP"}, 92 | AotErHVXC: subType{"AOT_ER_HVXC"}, 93 | AotErHILN: subType{"AOT_ER_HILN"}, 94 | AotErPARA: subType{"AOT_ER_PARA"}, 95 | AotRsvd28: subType{"AOT_RSVD_28"}, 96 | AotPS: subType{"AOT_PS"}, 97 | AotMPEGS: subType{"AOT_MPEGS"}, 98 | AotESCAPE: subType{"AOT_ESCAPE"}, 99 | AotMp3onMp4L1: subType{"AOT_MP3ONMP4_L1"}, 100 | AotMp3onMp4L2: subType{"AOT_MP3ONMP4_L2"}, 101 | AotMp3onMp4L3: subType{"AOT_MP3ONMP4_L3"}, 102 | AotRsvd35: subType{"AOT_RSVD_35"}, 103 | AotRsvd36: subType{"AOT_RSVD_36"}, 104 | AotAacSLS: subType{"AOT_AAC_SLS"}, 105 | AotSLS: subType{"AOT_SLS"}, 106 | AotErAacELD: subType{"AOT_ER_AAC_ELD"}, 107 | AotUSAC: subType{"AOT_USAC"}, 108 | AotSAOC: subType{"AOT_SAOC"}, 109 | AotLdMPEGS: subType{"AOT_LD_MPEGS"}, 110 | AotDrmAAC: subType{"AOT_DRM_AAC"}, 111 | AotDrmSBR: subType{"AOT_DRM_SBR"}, 112 | AotDrmMpegPS: subType{"AOT_DRM_MPEG_PSs"}, 113 | } 114 | 115 | // EncodeFrame エンコードを実行 116 | func (fdkaacEncoder *fdkaacEncoder) EncodeFrame( 117 | frame IFrame, 118 | callback func(frame *Frame) bool) bool { 119 | return encoderEncodeFrame((*encoder)(fdkaacEncoder), frame, callback) 120 | } 121 | 122 | // Close 閉じる 123 | func (fdkaacEncoder *fdkaacEncoder) Close() { 124 | encoderClose((*encoder)(fdkaacEncoder)) 125 | } 126 | 127 | // SetBitrate fdkaacのencode結果のbitrateを設定する bps 128 | func (fdkaacEncoder *fdkaacEncoder) SetBitrate(value uint32) bool { 129 | return bool(C.FdkaacEncoder_setBitrate(unsafe.Pointer(fdkaacEncoder.cEncoder), C.uint32_t(value))) 130 | } 131 | -------------------------------------------------------------------------------- /encoderJpeg.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | extern bool JpegEncoder_setQuality(void *encoder, uint32_t quality); 8 | */ 9 | import "C" 10 | import ( 11 | "unsafe" 12 | ) 13 | 14 | type jpegEncoder encoder 15 | 16 | // EncodeFrame エンコードを実行 17 | func (jpegEncoder *jpegEncoder) EncodeFrame( 18 | frame IFrame, 19 | callback func(frame *Frame) bool) bool { 20 | return encoderEncodeFrame((*encoder)(jpegEncoder), frame, callback) 21 | } 22 | 23 | // Close 閉じる 24 | func (jpegEncoder *jpegEncoder) Close() { 25 | encoderClose((*encoder)(jpegEncoder)) 26 | } 27 | 28 | // SetQuality jpegEncodeの動作qualityを設定する 0 - 100 29 | func (jpegEncoder *jpegEncoder) SetQuality(quality uint32) bool { 30 | return bool(C.JpegEncoder_setQuality(unsafe.Pointer(jpegEncoder.cEncoder), C.uint32_t(quality))) 31 | } 32 | -------------------------------------------------------------------------------- /encoderOpus.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | extern int OpusEncoder_codecControl(void *ptr, const char *key, int value); 7 | */ 8 | import "C" 9 | import ( 10 | "reflect" 11 | "unsafe" 12 | ) 13 | 14 | type opusEncoder encoder 15 | 16 | // OpusEncoderControls codecControlで設定可能な項目 17 | var OpusEncoderControls = struct { 18 | SetComplexity subType 19 | GetComplexity subType 20 | SetBitrate subType 21 | GetBitrate subType 22 | SetVBR subType 23 | GetVBR subType 24 | SetVBRConstraint subType 25 | GetVBRConstraint subType 26 | SetForceChannels subType 27 | GetForceChannels subType 28 | SetMaxBandwidth subType 29 | GetMaxBandwidth subType 30 | SetBandwidth subType 31 | SetSignal subType 32 | GetSignal subType 33 | SetApplication subType 34 | GetApplication subType 35 | GetLookahead subType 36 | SetInbandFEC subType 37 | GetInbandFEC subType 38 | SetPacketLossPERC subType 39 | GetPacketLossPERC subType 40 | SetDTX subType 41 | GetDTX subType 42 | SetLSBDepth subType 43 | GetLSBDepth subType 44 | SetExpertFrameDuration subType 45 | GetExpertFrameDuration subType 46 | SetPredictionDisabled subType 47 | GetPredictionDisabled subType 48 | ResetState subType 49 | GetFinalRange subType 50 | GetBandwidth subType 51 | GetSampleRate subType 52 | SetPhaseInversionDisabled subType 53 | GetPhaseInversionDisabled subType 54 | }{ 55 | subType{"OPUS_SET_COMPLEXITY"}, 56 | subType{"OPUS_GET_COMPLEXITY"}, 57 | subType{"OPUS_SET_BITRATE"}, 58 | subType{"OPUS_GET_BITRATE"}, 59 | subType{"OPUS_SET_VBR"}, 60 | subType{"OPUS_GET_VBR"}, 61 | subType{"OPUS_SET_VBR_CONSTRAINT"}, 62 | subType{"OPUS_GET_VBR_CONSTRAINT"}, 63 | subType{"OPUS_SET_FORCE_CHANNELS"}, 64 | subType{"OPUS_GET_FORCE_CHANNELS"}, 65 | subType{"OPUS_SET_MAX_BANDWIDTH"}, 66 | subType{"OPUS_GET_MAX_BANDWIDTH"}, 67 | subType{"OPUS_SET_BANDWIDTH"}, 68 | subType{"OPUS_SET_SIGNAL"}, 69 | subType{"OPUS_GET_SIGNAL"}, 70 | subType{"OPUS_SET_APPLICATION"}, 71 | subType{"OPUS_GET_APPLICATION"}, 72 | subType{"OPUS_GET_LOOKAHEAD"}, 73 | subType{"OPUS_SET_INBAND_FEC"}, 74 | subType{"OPUS_GET_INBAND_FEC"}, 75 | subType{"OPUS_SET_PACKET_LOSS_PERC"}, 76 | subType{"OPUS_GET_PACKET_LOSS_PERC"}, 77 | subType{"OPUS_SET_DTX"}, 78 | subType{"OPUS_GET_DTX"}, 79 | subType{"OPUS_SET_LSB_DEPTH"}, 80 | subType{"OPUS_GET_LSB_DEPTH"}, 81 | subType{"OPUS_SET_EXPERT_FRAME_DURATION"}, 82 | subType{"OPUS_GET_EXPERT_FRAME_DURATION"}, 83 | subType{"OPUS_SET_PREDICTION_DISABLED"}, 84 | subType{"OPUS_GET_PREDICTION_DISABLED"}, 85 | subType{"OPUS_RESET_STATE"}, 86 | subType{"OPUS_GET_FINAL_RANGE"}, 87 | subType{"OPUS_GET_BANDWIDTH"}, 88 | subType{"OPUS_GET_SAMPLE_RATE"}, 89 | subType{"OPUS_SET_PHASE_INVERSION_DISABLED"}, 90 | subType{"OPUS_GET_PHASE_INVERSION_DISABLED"}, 91 | } 92 | 93 | func (opusEncoder *opusEncoder) EncodeFrame( 94 | frame IFrame, 95 | callback func(frame *Frame) bool) bool { 96 | return encoderEncodeFrame((*encoder)(opusEncoder), frame, callback) 97 | } 98 | 99 | // Close 閉じる 100 | func (opusEncoder *opusEncoder) Close() { 101 | encoderClose((*encoder)(opusEncoder)) 102 | } 103 | 104 | // SetCodecControl 追加パラメーター設定 105 | func (opusEncoder *opusEncoder) SetCodecControl(control subType, value interface{}) { 106 | ckey := C.CString(control.value) 107 | defer C.free(unsafe.Pointer(ckey)) 108 | // valueについて、reflectでなんとかしなければならない 109 | ivalue := 0 110 | switch reflect.TypeOf(value).Kind() { 111 | case reflect.Uint32: 112 | ivalue = int(value.(uint32)) 113 | case reflect.Int: 114 | ivalue = value.(int) 115 | case reflect.Int32: 116 | ivalue = int(value.(int32)) 117 | case reflect.Bool: 118 | if value.(bool) { 119 | ivalue = 1 120 | } 121 | } 122 | C.OpusEncoder_codecControl(unsafe.Pointer(opusEncoder.cEncoder), ckey, C.int(ivalue)) 123 | } 124 | 125 | // GetCodecControl 追加パラメーター参照 126 | func (opusEncoder *opusEncoder) GetCodecControl(control subType) int32 { 127 | ckey := C.CString(control.value) 128 | defer C.free(unsafe.Pointer(ckey)) 129 | return int32(C.OpusEncoder_codecControl(unsafe.Pointer(opusEncoder.cEncoder), ckey, C.int(0))) 130 | } 131 | -------------------------------------------------------------------------------- /encoderX264.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | extern bool X264Encoder_forceNextFrameType(void *encoder, const char *type); 8 | */ 9 | import "C" 10 | import ( 11 | "unsafe" 12 | ) 13 | 14 | type x264Encoder encoder 15 | 16 | // X264EncoderFrameTypes X264で指定できる、frameTypeリスト 17 | var X264EncoderFrameTypes = struct { 18 | I subType 19 | P subType 20 | B subType 21 | IDR subType 22 | Auto subType 23 | Bref subType 24 | KeyFrame subType 25 | }{ 26 | subType{"I"}, 27 | subType{"P"}, 28 | subType{"B"}, 29 | subType{"IDR"}, 30 | subType{"Auto"}, 31 | subType{"Bref"}, 32 | subType{"KeyFrame"}, 33 | } 34 | 35 | // EncodeFrame エンコードを実行 36 | func (x264Encoder *x264Encoder) EncodeFrame( 37 | frame IFrame, 38 | callback func(frame *Frame) bool) bool { 39 | return encoderEncodeFrame((*encoder)(x264Encoder), frame, callback) 40 | } 41 | 42 | // Close 閉じる 43 | func (x264Encoder *x264Encoder) Close() { 44 | encoderClose((*encoder)(x264Encoder)) 45 | } 46 | 47 | func (x264Encoder *x264Encoder) ForceNextFrameType(frameType subType) bool { 48 | ctype := C.CString(frameType.value) 49 | defer C.free(unsafe.Pointer(ctype)) 50 | return bool(C.X264Encoder_forceNextFrameType(unsafe.Pointer(x264Encoder.cEncoder), ctype)) 51 | } 52 | -------------------------------------------------------------------------------- /encoderX265.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | extern bool X265Encoder_forceNextFrameType(void *encoder, const char *type); 8 | */ 9 | import "C" 10 | import ( 11 | "unsafe" 12 | ) 13 | 14 | type x265Encoder encoder 15 | 16 | // X265EncoderFrameTypes X264で指定できる、frameTypeリスト 17 | var X265EncoderFrameTypes = struct { 18 | I subType 19 | P subType 20 | B subType 21 | IDR subType 22 | Auto subType 23 | Bref subType 24 | }{ 25 | subType{"I"}, 26 | subType{"P"}, 27 | subType{"B"}, 28 | subType{"IDR"}, 29 | subType{"Auto"}, 30 | subType{"Bref"}, 31 | } 32 | 33 | // EncodeFrame エンコードを実行 34 | func (x265Encoder *x265Encoder) EncodeFrame( 35 | frame IFrame, 36 | callback func(frame *Frame) bool) bool { 37 | return encoderEncodeFrame((*encoder)(x265Encoder), frame, callback) 38 | } 39 | 40 | // Close 閉じる 41 | func (x265Encoder *x265Encoder) Close() { 42 | encoderClose((*encoder)(x265Encoder)) 43 | } 44 | 45 | func (x265Encoder *x265Encoder) ForceNextFrameType(frameType subType) bool { 46 | ctype := C.CString(frameType.value) 47 | defer C.free(unsafe.Pointer(ctype)) 48 | return bool(C.X265Encoder_forceNextFrameType(unsafe.Pointer(x265Encoder.cEncoder), ctype)) 49 | } 50 | -------------------------------------------------------------------------------- /frame.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include "ttLibC/ttLibC/frame/frame.h" 8 | extern void Frame_getFrameType(void *cFrame, char *buffer, size_t buffer_size); 9 | extern uint64_t Frame_getPts(void *frame); 10 | extern uint64_t Frame_getDts(void *frame); 11 | extern uint32_t Frame_getTimebase(void *frame); 12 | extern uint32_t Frame_getID(void *frame); 13 | extern void Frame_close(void *frame); 14 | extern ttLibC_Frame *Frame_clone(void *frame); 15 | extern void *newGoFrame(uint64_t pts, uint64_t dts, uint32_t timebase, uint32_t id, 16 | uint32_t width, uint32_t height, 17 | uint32_t sampleRate, uint32_t sampleNum, uint32_t channelNum, 18 | uint64_t dataPos, uint32_t widthStride, 19 | uint64_t yDataPos, uint32_t yStride, 20 | uint64_t uDataPos, uint32_t uStride, 21 | uint64_t vDataPos, uint32_t vStride); 22 | extern void deleteGoFrame(void *frame); 23 | extern bool Frame_getBinaryBuffer(uintptr_t ptr, void *frame, void *goFrame); 24 | */ 25 | import "C" 26 | import ( 27 | "bytes" 28 | "unsafe" 29 | ) 30 | 31 | // cttLibCFrame c言語のframeデータ 32 | type cttLibCFrame unsafe.Pointer 33 | 34 | // IFrame Frameのインターフェイス 35 | type IFrame interface { 36 | newGoRefFrame() unsafe.Pointer 37 | refCFrame() cttLibCFrame 38 | deleteGoRefFrame(ptr unsafe.Pointer) 39 | ToFrame() *Frame 40 | GetBinaryBuffer(callback func(data []byte) bool) bool 41 | } 42 | 43 | // frameType frameタイプ 44 | type frameType struct{ value string } 45 | 46 | // subType subタイプ 47 | type subType struct{ value string } 48 | 49 | // FrameTypes Frameタイプリスト 50 | var FrameTypes = struct { 51 | Bgr frameType 52 | Flv1 frameType 53 | H264 frameType 54 | H265 frameType 55 | Jpeg frameType 56 | Png frameType 57 | Theora frameType 58 | Vp6 frameType 59 | Vp8 frameType 60 | Vp9 frameType 61 | Wmv1 frameType 62 | Wmv2 frameType 63 | Yuv420 frameType 64 | Aac frameType 65 | AdpcmImaWav frameType 66 | Mp3 frameType 67 | Nellymoser frameType 68 | Opus frameType 69 | PcmAlaw frameType 70 | PcmF32 frameType 71 | PcmMulaw frameType 72 | PcmS16 frameType 73 | Speex frameType 74 | Vorbis frameType 75 | Unknown frameType 76 | }{ 77 | frameType{"bgr"}, 78 | frameType{"flv1"}, 79 | frameType{"h264"}, 80 | frameType{"h265"}, 81 | frameType{"jpeg"}, 82 | frameType{"png"}, 83 | frameType{"theora"}, 84 | frameType{"vp6"}, 85 | frameType{"vp8"}, 86 | frameType{"vp9"}, 87 | frameType{"wmv1"}, 88 | frameType{"wmv2"}, 89 | frameType{"yuv420"}, 90 | frameType{"aac"}, 91 | frameType{"adpcmImaWav"}, 92 | frameType{"mp3"}, 93 | frameType{"nellymoser"}, 94 | frameType{"opus"}, 95 | frameType{"pcmAlaw"}, 96 | frameType{"pcmF32"}, 97 | frameType{"pcmMulaw"}, 98 | frameType{"pcmS16"}, 99 | frameType{"speex"}, 100 | frameType{"vorbis"}, 101 | frameType{""}, 102 | } 103 | 104 | // Frame フレーム 105 | type Frame struct { 106 | // Type 対ーぷ 107 | Type frameType 108 | Pts uint64 109 | Dts uint64 110 | Timebase uint32 111 | ID uint32 112 | 113 | cFrame cttLibCFrame 114 | hasBody bool // このデータが解放する時に、closeすべきかのフラグ 115 | } 116 | 117 | // init データを使って初期化します。 118 | func (frame *Frame) init(cframe cttLibCFrame) { 119 | // cのframeデータを元にどういうデータであるかを取得しなければならない。 120 | if cframe == nil { 121 | panic("nullなデータのframe初期化を実施しようとしました。") 122 | } 123 | frame.cFrame = cframe 124 | buf := make([]byte, 256) 125 | ptr := unsafe.Pointer(cframe) 126 | C.Frame_getFrameType(ptr, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(256)) 127 | name := string(buf[:bytes.IndexByte(buf, 0)]) 128 | frame.Type = frameType{name} 129 | frame.ID = uint32(C.Frame_getID(ptr)) 130 | frame.Pts = uint64(C.Frame_getPts(ptr)) 131 | frame.Dts = uint64(C.Frame_getDts(ptr)) 132 | frame.Timebase = uint32(C.Frame_getTimebase(ptr)) 133 | } 134 | 135 | // Close フレームを解放します 136 | func (frame *Frame) Close() { 137 | if frame.hasBody { 138 | C.Frame_close(unsafe.Pointer(frame.cFrame)) 139 | } 140 | frame.cFrame = nil 141 | } 142 | 143 | // Clone フレームのcloneを作成し、応答します 144 | func (frame *Frame) Clone() *Frame { 145 | clonedCFrame := C.Frame_clone(unsafe.Pointer(frame.cFrame)) 146 | if clonedCFrame == nil { 147 | return nil 148 | } 149 | frame.init(cttLibCFrame(clonedCFrame)) 150 | frame.hasBody = true 151 | return frame 152 | } 153 | 154 | // newGoRefFrame goの配列データをcの世界に持っていくデータを構築する 155 | func (frame *Frame) newGoRefFrame() unsafe.Pointer { 156 | return C.newGoFrame(C.uint64_t(frame.Pts), C.uint64_t(frame.Dts), C.uint32_t(frame.Timebase), C.uint32_t(frame.ID), 157 | 0, 0, 158 | 0, 0, 0, 159 | 0, 0, 160 | 0, 0, 161 | 0, 0, 162 | 0, 0) 163 | } 164 | 165 | func (frame *Frame) ToFrame() *Frame { 166 | return frame 167 | } 168 | 169 | // refCFrame interface経由でcframe参照 170 | func (frame *Frame) refCFrame() cttLibCFrame { 171 | return frame.cFrame 172 | } 173 | 174 | // deleteGoRefFrame cの世界に持っていったデータを破棄する 175 | func (frame *Frame) deleteGoRefFrame(ptr unsafe.Pointer) { 176 | C.deleteGoFrame(ptr) 177 | } 178 | 179 | // getFrameBinaryBuffer frameのbyteデータを参照します 180 | func getFrameBinaryBuffer(frame IFrame, callback func(data []byte) bool) bool { 181 | call := new(dataCall) 182 | call.callback = callback 183 | goFrame := frame.newGoRefFrame() 184 | defer frame.deleteGoRefFrame(goFrame) 185 | return bool(C.Frame_getBinaryBuffer(C.uintptr_t(uintptr(unsafe.Pointer(call))), unsafe.Pointer(frame.refCFrame()), goFrame)) 186 | } 187 | 188 | // GetBinaryBuffer binaryデータを参照する 189 | func (frame *Frame) GetBinaryBuffer(callback func(data []byte) bool) bool { 190 | return getFrameBinaryBuffer(frame, callback) 191 | } 192 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file log.h 3 | * @brief log support. 4 | * 5 | * this code is under 3-Cause BSD license. 6 | * 7 | * @author taktod 8 | * @date 2015/07/12 9 | */ 10 | 11 | #ifndef TTLIBC_LOG_H_ 12 | #define TTLIBC_LOG_H_ 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | #ifndef __DEBUG_FLAG__ 21 | # define __DEBUG_FLAG__ 1 22 | #endif 23 | 24 | /** 25 | * output log data. only for debug compile 26 | * @param fmt format string 27 | * @param ... data for format string 28 | */ 29 | #if __DEBUG_FLAG__ == 1 30 | # define LOG_PRINT(fmt, ...) \ 31 | printf("[log]%s(): " fmt "\n", __func__, ## __VA_ARGS__) 32 | #else 33 | # define LOG_PRINT(fmt, ...) 34 | #endif 35 | 36 | /** 37 | * output error data for strerr. 38 | * @param fmt format string 39 | * @param ... data for format string 40 | */ 41 | #define ERR_PRINT(fmt, ...) \ 42 | fprintf(stderr, "[log]%s(): " fmt "\n", __func__, ## __VA_ARGS__) 43 | 44 | #ifdef __cplusplus 45 | } /* extern "C" */ 46 | #endif 47 | 48 | #endif /* TTLIBC_LOG_H_ */ 49 | -------------------------------------------------------------------------------- /memo.md: -------------------------------------------------------------------------------- 1 | # 概要 2 | 3 | ttLibGoを作り直した。 4 | 今回は起動時にcmakeとmakeを実行 5 | 作成したshared libraryにdlopenでアクセスして利用する形にしました。 6 | 7 | dylibかsoがあるなら、buildする必要はないんですが、ttLibGoのデータが新しくなったときにbuildしなおしてくれないので、とりあえず毎回buildにしてみた。 8 | 9 | ひととおり動作を調整したけど、fdkaacはttLibCにはいってないので、未実装状態 10 | これは、別でソースコードをいれておいて、対応可能にしておきたいところ。 11 | 12 | とりあえず、ubuntu環境(docker)でテストしてみたところだけど、 13 | stdintがみえなくて動作しないがいくつか (みえるようにした。) 14 | c++11がはいってないので動作しないもいくつか (apt installでいれた。) 15 | cmakeもいれないとだめ。 16 | ttLibCのCMakeListsがこけた・・・なんだこれ・・・ 17 | 18 | add_compile_definitionをadd_definitionに変更 19 | cmake 10.系では利用できないっぽい。 20 | checkLibraryのheaderの確認をかきかえ。 21 | 現状のままでは、みつからないときにbuildがこける。 22 | -> 直した 23 | 24 | dockerのubuntuでテストしてみた。 25 | 26 | ``` 27 | $ docker run -it ubuntu:latest /bin/bash 28 | # apt update 29 | # apt upgrade 30 | # apt install git golang cmake c++11 vim 31 | # useradd taktod 32 | # su - taktod 33 | $ go get github.com/taktod/ttLibGo 34 | $ vi test.go 35 | ``` 36 | 37 | ```test.go 38 | package main 39 | 40 | import ( 41 | "fmt" 42 | "github.com/taktod/ttLibGo" 43 | ) 44 | func main() { 45 | fmt.Println("hello") 46 | reader := ttLibGo.Readers.Flv() 47 | defer reader.Close() 48 | } 49 | ``` 50 | 51 | ``` 52 | $ go run test.go 53 | /home/taktod/go/src/github.com/taktod/ttLibGo/build/libttLibC.so 54 | hello 55 | $ 56 | ``` 57 | 58 | とりあえずこれで動いてくれた。 59 | -------------------------------------------------------------------------------- /reader.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "ttLibC/ttLibC/container/container.h" 9 | 10 | extern ttLibC_ContainerReader *ContainerReader_make(const char *format); 11 | 12 | // 読み込み実施 13 | extern bool ContainerReader_read( 14 | ttLibC_ContainerReader *reader, 15 | void *data, 16 | size_t data_size, 17 | uintptr_t ptr); 18 | extern void ContainerReader_close(ttLibC_ContainerReader *reader); 19 | */ 20 | import "C" 21 | import "unsafe" 22 | 23 | // readerType readerタイプ 24 | type readerType struct{ value string } 25 | 26 | type IReader interface { 27 | ReadFrame( 28 | binary []byte, 29 | length uint64, 30 | callback func(frame *Frame) bool) bool 31 | Close() 32 | } 33 | 34 | // reader メディアデータ読み込み 35 | type reader struct { 36 | Type readerType 37 | cReader *C.ttLibC_ContainerReader 38 | call frameCall 39 | } 40 | 41 | // ReaderTypes Readerタイプリスト 42 | var ReaderTypes = struct { 43 | Flv readerType 44 | Mp4 readerType 45 | Mkv readerType 46 | Webm readerType 47 | Mpegts readerType 48 | }{ 49 | readerType{"flv"}, 50 | readerType{"mp4"}, 51 | readerType{"mkv"}, 52 | readerType{"webm"}, 53 | readerType{"mpegts"}, 54 | } 55 | 56 | // readerInit 初期化共通関数 57 | func readerInit(readerType readerType) *reader { 58 | reader := new(reader) 59 | reader.Type = readerType 60 | cFormat := C.CString(reader.Type.value) 61 | defer C.free(unsafe.Pointer(cFormat)) 62 | reader.cReader = C.ContainerReader_make(cFormat) 63 | if reader.cReader == nil { 64 | return nil 65 | } 66 | return reader 67 | } 68 | 69 | // Readers Readers処理 70 | var Readers = struct { 71 | // Flv FlvReaderを作ります 72 | Flv func() *reader 73 | Mkv func() *reader 74 | Webm func() *reader 75 | Mp4 func() *reader 76 | Mpegts func() *reader 77 | }{ 78 | Flv: func() *reader { 79 | return readerInit(ReaderTypes.Flv) 80 | }, 81 | Mkv: func() *reader { 82 | return readerInit(ReaderTypes.Mkv) 83 | }, 84 | Webm: func() *reader { 85 | return readerInit(ReaderTypes.Webm) 86 | }, 87 | Mp4: func() *reader { 88 | return readerInit(ReaderTypes.Mp4) 89 | }, 90 | Mpegts: func() *reader { 91 | return readerInit(ReaderTypes.Mpegts) 92 | }, 93 | } 94 | 95 | // ReadFrame Frame読み込み 96 | func (reader *reader) ReadFrame( 97 | binary []byte, 98 | length uint64, 99 | callback func(frame *Frame) bool) bool { 100 | if reader.cReader == nil { 101 | return false 102 | } 103 | reader.call.callback = callback 104 | if !C.ContainerReader_read( 105 | reader.cReader, 106 | unsafe.Pointer(&binary[0]), 107 | C.size_t(length), 108 | C.uintptr_t(uintptr(unsafe.Pointer(&reader.call)))) { 109 | return false 110 | } 111 | return true 112 | } 113 | 114 | // Close 閉じる 115 | func (reader *reader) Close() { 116 | C.ContainerReader_close(reader.cReader) 117 | reader.cReader = nil 118 | } 119 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ttLibGO 2 | 3 | # 概要 4 | 5 | go言語でttLibCの変換ライブラリを使う動作 6 | 7 | これを使うとflvやmkvといったコンテナデータの読み込み 8 | 内部に定義されているframeデータを取り出すことができます。 9 | 10 | 取り出したframeデータはffmpegのavcodecでdecodeしたり 11 | fdkaacやx264でencodeしたりできる。 12 | 13 | もっと簡単にいろんな人が映像変換を楽しめるようになったらいいなと思います。 14 | 15 | なお、このライブラリは、latencyを極力減らしてリアルタイム処理をする関係上 16 | 意図的に出力コンテナの情報をカットしたりしたりしてます。 17 | 18 | # 作者 19 | 20 | taktod 21 | twitter: https://twitter.com/taktod 22 | email: poepoemix@hotmail.com 23 | 24 | # ライセンス 25 | 26 | GPLv3 27 | 28 | # 使い方 29 | 30 | linuxもしくはmacで 31 | 32 | ``` 33 | $ go get github.com/taktod/ttLibGo 34 | ``` 35 | 36 | これで使えるようになると思います。 37 | 38 | # 具体的な書き方 39 | 40 | ## まず適当にmp4でも読み込むことにします。 41 | 42 | ```test.go 43 | package main 44 | 45 | import ( 46 | "os" 47 | ) 48 | 49 | func main() { 50 | in, err := os.Open("test.h264.aac.mp4") 51 | if err != nil { 52 | panic(err) 53 | } 54 | for { 55 | buffer := make([]byte, 65536) 56 | length, err := in.Read(buffer) 57 | if length == 0 { 58 | break 59 | } 60 | if err != nil { 61 | panic(err) 62 | } 63 | } 64 | } 65 | ``` 66 | 67 | ## とりあえず、mp4を読み込むので、ttLibGo -> Readers -> Mp4を選択 68 | コンテナReaderはttLibGo.Readersにまとめてあります。 69 | 70 | ``` 71 | in, err := os.Open("test.h264.aac.mp4") 72 | if err != nil { 73 | panic(err) 74 | } 75 | reader := ttLibGo.Readers.Mp4() 76 | defer reader.Close() 77 | for { 78 | buffer := make([]byte, 65536) 79 | ``` 80 | 81 | 処理がおわったらcloseしたいので、deferで指定しとく 82 | 83 | ## bufferに読み取ったデータをreaderに渡してframeを取り出す。 84 | 85 | ``` 86 | for { 87 | buffer := make([]byte, 65536) 88 | length, err := in.Read(buffer) 89 | if length == 0 { 90 | break 91 | } 92 | if err != nil { 93 | panic(err) 94 | } 95 | if !reader.ReadFrame(buffer, uint64(length), func(frame *ttLibGo.Frame) bool { 96 | fmt.Println(frame) 97 | return true 98 | }) { 99 | panic("error on read frame.") 100 | } 101 | } 102 | ``` 103 | 104 | これでフレームがざざーっと表示される。 105 | 106 | ``` 107 | ... 108 | &{{h264} 2102368 0 16000 1 0x6502160 false} 109 | &{{h264} 2102896 0 16000 1 0x6502160 false} 110 | &{{h264} 2103440 0 16000 1 0x6502160 false} 111 | &{{h264} 2103968 0 16000 1 0x6502160 false} 112 | &{{h264} 2104512 0 16000 1 0x6502160 false} 113 | &{{h264} 2105040 0 16000 1 0x6502160 false} 114 | &{{h264} 2105568 0 16000 1 0x6502160 false} 115 | &{{h264} 2106112 0 16000 1 0x6502160 false} 116 | &{{aac} 0 0 44100 2 0x6400730 false} 117 | &{{aac} 0 0 44100 2 0x6400730 false} 118 | &{{aac} 1024 0 44100 2 0x6400730 false} 119 | &{{aac} 2048 0 44100 2 0x6400730 false} 120 | &{{aac} 3072 0 44100 2 0x6400730 false} 121 | &{{aac} 4096 0 44100 2 0x6400730 false} 122 | &{{aac} 5120 0 44100 2 0x6400730 false} 123 | &{{aac} 6144 0 44100 2 0x6400730 false} 124 | &{{aac} 7168 0 44100 2 0x6400730 false} 125 | ... 126 | ``` 127 | 128 | 129 | ## typeでどんなフレームか確認 130 | 131 | プログラム的にフレームがなんであるか知りたい場合は、Frame.Typeを利用すればよい。 132 | サポートしているタイプはttLibGo.FrameTypesにまとめてあります。 133 | 134 | ``` 135 | switch(frame.Type) { 136 | case ttLibGo.FrameTypes.H264: 137 | // h264の場合の処理 138 | case ttLibGo.FrameTypes.Aac: 139 | // aacの場合の処理 140 | } 141 | ``` 142 | 143 | ## より詳細な情報を取得 144 | 145 | より詳細な情報を取得する場合は、こんな具合 146 | ttLibGo.{Frame}.Castを利用すると詳細なデータにできます。 147 | 148 | ``` 149 | switch(frame.Type) { 150 | case ttLibGo.FrameTypes.H264: 151 | fmt.Println(ttLibGo.H264.Cast(frame)) 152 | } 153 | ``` 154 | 155 | 結果 156 | ``` 157 | &{{h264} 0 0 16000 1 0xad00270 false} 158 | &{{h264} 0 0 16000 1 {info} 640 360 {configData} 4294967295 false 0xad00270} 159 | &{{h264} 0 0 16000 1 0xad00270 false} 160 | &{{h264} 0 0 16000 1 {key} 640 360 {sliceIDR} 2 false 0xad00270} 161 | &{{h264} 528 0 16000 1 0xad00270 false} 162 | &{{h264} 528 0 16000 1 {inner} 640 360 {slice} 0 false 0xad00270} 163 | ``` 164 | 165 | ## avcodecDecoderでh264をdecodeしてみる。 166 | 167 | avcodecDecoder (ffmpegのやつ)でdecodeしてみる。 168 | readerの後ろのところで、decoderを準備してやる。 169 | 170 | ``` 171 | reader := ttLibGo.Readers.Mp4() 172 | defer reader.Close() 173 | var decoder ttLibGo.IDecoder 174 | defer func() { 175 | if decoder != nil { 176 | decoder.Close() 177 | } 178 | }() 179 | for { 180 | buffer := make([]byte, 65536) 181 | ``` 182 | 183 | とりあえず、interfaceだけ準備しておいて値が設定されてたらcloseする形にする。 184 | 185 | ## 実際にdecodeするコードを書く 186 | 187 | typeを確認したところで、decoderが準備されてなかったら、準備するようにしとく 188 | decoderは例によってttLibGo.Decodersにすべてまとめてある。 189 | 今回は映像の変換なので、AvcodecVideoを選択 190 | 191 | ``` 192 | switch frame.Type { 193 | case ttLibGo.FrameTypes.H264: 194 | h264 := ttLibGo.H264.Cast(frame) 195 | if decoder == nil { 196 | decoder = ttLibGo.Decoders.AvcodecVideo(h264.Type, h264.Width, h264.Height) 197 | } 198 | return decoder.DecodeFrame(h264, func(frame *ttLibGo.Frame) bool { 199 | fmt.Println(frame) 200 | return true 201 | }) 202 | case ttLibGo.FrameTypes.Aac: 203 | ``` 204 | 205 | 結果 206 | 207 | ``` 208 | &{{yuv420} 0 0 16000 1 0x7507f50 false} 209 | &{{yuv420} 528 0 16000 1 0x7507f50 false} 210 | &{{yuv420} 1072 0 16000 1 0x7507f50 false} 211 | &{{yuv420} 1600 0 16000 1 0x7507f50 false} 212 | &{{yuv420} 2128 0 16000 1 0x7507f50 false} 213 | &{{yuv420} 2672 0 16000 1 0x7507f50 false} 214 | ``` 215 | 216 | h264のデータがyuv420に変換されてることがわかる。 -------------------------------------------------------------------------------- /resampler.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | 8 | extern void *Resampler_make(void *mp); 9 | extern bool Resampler_resampleFrame(void *resampler, void *frame, void *goFrame, uintptr_t ptr); 10 | extern void Resampler_close(void *resampler); 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | // cttlibCResampler c言語のresampler 18 | type cttlibCResampler unsafe.Pointer 19 | 20 | // resamplerType resamplerタイプ 21 | type resamplerType struct{ value string } 22 | 23 | // IResampler リサンプラ 24 | type IResampler interface { 25 | ResampleFrame( 26 | frame IFrame, 27 | callback func(frame *Frame) bool) bool 28 | Close() 29 | } 30 | 31 | // resampler リサンプラ 32 | type resampler struct { 33 | Type resamplerType 34 | cResampler cttlibCResampler 35 | call frameCall 36 | } 37 | 38 | // ResamplerTypes Resamplerタイプリスト 39 | var ResamplerTypes = struct { 40 | Audio resamplerType 41 | Image resamplerType 42 | Libyuv resamplerType 43 | Resize resamplerType 44 | Soundtouch resamplerType 45 | Speexdsp resamplerType 46 | Swresample resamplerType 47 | Swscale resamplerType 48 | }{ 49 | resamplerType{"audio"}, 50 | resamplerType{"image"}, 51 | resamplerType{"libyuv"}, 52 | resamplerType{"resize"}, 53 | resamplerType{"soundtouch"}, 54 | resamplerType{"speexdsp"}, 55 | resamplerType{"swresample"}, 56 | resamplerType{"swscale"}, 57 | } 58 | 59 | // Resamplers Resamplers処理 60 | var Resamplers = struct { 61 | Audio func(frameType frameType, subType subType) *resampler 62 | Image func() *imageResampler 63 | Libyuv func() *libyuvResampler 64 | Resize func() *resizeResampler 65 | Soundtouch func(sampleRate uint32, channelNum uint32) *soundtouchResampler 66 | Speexdsp func(inSampleRate uint32, outSampleRate uint32, channelNum uint32, quality uint32) *resampler 67 | Swresample func(inType frameType, inSubType subType, inSampleRate uint32, inChannelNum uint32, 68 | outType frameType, outSubtype subType, outSampleRate uint32, outChannelNum uint32) *resampler 69 | Swscale func(inType frameType, inSubType subType, inWidth uint32, inHeight uint32, 70 | outType frameType, outSubType subType, outWidth uint32, outHeight uint32, 71 | mode subType) *swscaleResampler 72 | }{ 73 | Audio: func(frameType frameType, subType subType) *resampler { 74 | resampler := new(resampler) 75 | resampler.Type = ResamplerTypes.Audio 76 | params := map[string]interface{}{ 77 | "resampler": resampler.Type.value, 78 | "frameType": frameType.value, 79 | "subType": subType.value, 80 | } 81 | v := mapUtil.fromMap(params) 82 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 83 | mapUtil.close(v) 84 | return resampler 85 | }, 86 | Image: func() *imageResampler { 87 | resampler := new(imageResampler) 88 | resampler.Type = ResamplerTypes.Image 89 | params := map[string]interface{}{ 90 | "resampler": resampler.Type.value, 91 | } 92 | v := mapUtil.fromMap(params) 93 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 94 | mapUtil.close(v) 95 | return resampler 96 | }, 97 | Libyuv: func() *libyuvResampler { 98 | resampler := new(libyuvResampler) 99 | resampler.Type = ResamplerTypes.Libyuv 100 | params := map[string]interface{}{ 101 | "resampler": resampler.Type.value, 102 | } 103 | v := mapUtil.fromMap(params) 104 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 105 | mapUtil.close(v) 106 | return resampler 107 | }, 108 | Resize: func() *resizeResampler { 109 | resampler := new(resizeResampler) 110 | resampler.Type = ResamplerTypes.Resize 111 | params := map[string]interface{}{ 112 | "resampler": resampler.Type.value, 113 | } 114 | v := mapUtil.fromMap(params) 115 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 116 | mapUtil.close(v) 117 | return resampler 118 | }, 119 | Soundtouch: func(sampleRate uint32, channelNum uint32) *soundtouchResampler { 120 | resampler := new(soundtouchResampler) 121 | resampler.Type = ResamplerTypes.Soundtouch 122 | params := map[string]interface{}{ 123 | "resampler": resampler.Type.value, 124 | "sampleRate": sampleRate, 125 | "channelNum": channelNum, 126 | } 127 | v := mapUtil.fromMap(params) 128 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 129 | mapUtil.close(v) 130 | return resampler 131 | }, 132 | Speexdsp: func(inSampleRate uint32, outSampleRate uint32, channelNum uint32, quality uint32) *resampler { 133 | resampler := new(resampler) 134 | resampler.Type = ResamplerTypes.Speexdsp 135 | params := map[string]interface{}{ 136 | "resampler": resampler.Type.value, 137 | "inSampleRate": inSampleRate, 138 | "outSampleRate": outSampleRate, 139 | "channelNum": channelNum, 140 | "quality": quality, 141 | } 142 | v := mapUtil.fromMap(params) 143 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 144 | mapUtil.close(v) 145 | return resampler 146 | }, 147 | Swresample: func(inType frameType, inSubType subType, inSampleRate uint32, inChannelNum uint32, 148 | outType frameType, outSubType subType, outSampleRate uint32, outChannelNum uint32) *resampler { 149 | resampler := new(resampler) 150 | resampler.Type = ResamplerTypes.Swresample 151 | params := map[string]interface{}{ 152 | "resampler": resampler.Type.value, 153 | "inType": inType.value, 154 | "inSubType": inSubType.value, 155 | "inSampleRate": inSampleRate, 156 | "inChannelNum": inChannelNum, 157 | "outType": outType.value, 158 | "outSubType": outSubType.value, 159 | "outSampleRate": outSampleRate, 160 | "outChannelNum": outChannelNum, 161 | } 162 | v := mapUtil.fromMap(params) 163 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 164 | mapUtil.close(v) 165 | return resampler 166 | }, 167 | Swscale: func(inType frameType, inSubType subType, inWidth uint32, inHeight uint32, 168 | outType frameType, outSubType subType, outWidth uint32, outHeight uint32, 169 | mode subType) *swscaleResampler { 170 | resampler := new(swscaleResampler) 171 | resampler.Type = ResamplerTypes.Swscale 172 | params := map[string]interface{}{ 173 | "resampler": resampler.Type.value, 174 | "inType": inType.value, 175 | "inSubType": inSubType.value, 176 | "inWidth": inWidth, 177 | "inHeight": inHeight, 178 | "outType": outType.value, 179 | "outSubType": outSubType.value, 180 | "outWidth": outWidth, 181 | "outHeight": outHeight, 182 | "mode": mode.value, 183 | } 184 | v := mapUtil.fromMap(params) 185 | resampler.cResampler = cttlibCResampler(C.Resampler_make(v)) 186 | mapUtil.close(v) 187 | return resampler 188 | }, 189 | } 190 | 191 | func resamplerResampleFrame( 192 | resampler *resampler, 193 | frame IFrame, 194 | callback func(frame *Frame) bool) bool { 195 | if resampler.cResampler == nil { 196 | return false 197 | } 198 | if frame == nil { 199 | return true 200 | } 201 | cframe := frame.newGoRefFrame() 202 | resampler.call.callback = callback 203 | result := C.Resampler_resampleFrame( 204 | unsafe.Pointer(resampler.cResampler), 205 | unsafe.Pointer(frame.refCFrame()), 206 | cframe, 207 | C.uintptr_t(uintptr(unsafe.Pointer(&resampler.call)))) 208 | frame.deleteGoRefFrame(cframe) 209 | return bool(result) 210 | } 211 | 212 | func resamplerClose(resampler *resampler) { 213 | C.Resampler_close(unsafe.Pointer(resampler.cResampler)) 214 | } 215 | 216 | // ResampleFrame リサンプルを実行 217 | func (resampler *resampler) ResampleFrame( 218 | frame IFrame, 219 | callback func(frame *Frame) bool) bool { 220 | return resamplerResampleFrame(resampler, frame, callback) 221 | } 222 | 223 | // Close 閉じる 224 | func (resampler *resampler) Close() { 225 | resamplerClose(resampler) 226 | } 227 | -------------------------------------------------------------------------------- /resamplerImage.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | extern bool ImageResampler_toBgr( 9 | void *resampler, 10 | void *dstCFrame, void *dstGoFrame, 11 | void *srcCFrame, void *srcGoFrame); 12 | 13 | extern bool ImageResampler_toYuv420( 14 | void *resampler, 15 | void *dstCFrame, void *dstGoFrame, 16 | void *srcCFrame, void *srcGoFrame); 17 | */ 18 | import "C" 19 | import ( 20 | "unsafe" 21 | ) 22 | 23 | type imageResampler resampler 24 | 25 | func (imageResampler *imageResampler) Close() { 26 | resamplerClose((*resampler)(imageResampler)) 27 | } 28 | 29 | func (imageResampler *imageResampler) ToBgr( 30 | dst IFrame, 31 | src IFrame) bool { 32 | dstGoFrame := dst.newGoRefFrame() 33 | srcGoFrame := src.newGoRefFrame() 34 | defer dst.deleteGoRefFrame(dstGoFrame) 35 | defer src.deleteGoRefFrame(srcGoFrame) 36 | return bool(C.ImageResampler_toBgr(unsafe.Pointer(imageResampler.cResampler), 37 | unsafe.Pointer(dst.refCFrame()), 38 | dstGoFrame, 39 | unsafe.Pointer(src.refCFrame()), 40 | srcGoFrame)) 41 | } 42 | 43 | func (imageResampler *imageResampler) ToYuv( 44 | dst IFrame, 45 | src IFrame) bool { 46 | dstGoFrame := dst.newGoRefFrame() 47 | srcGoFrame := src.newGoRefFrame() 48 | defer dst.deleteGoRefFrame(dstGoFrame) 49 | defer src.deleteGoRefFrame(srcGoFrame) 50 | return bool(C.ImageResampler_toYuv420(unsafe.Pointer(imageResampler.cResampler), 51 | unsafe.Pointer(dst.refCFrame()), 52 | dstGoFrame, 53 | unsafe.Pointer(src.refCFrame()), 54 | srcGoFrame)) 55 | } 56 | -------------------------------------------------------------------------------- /resamplerLibyuv.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | extern bool LibyuvResampler_resize( 9 | void *resampler, 10 | void *dstCFrame, void *dstGoFrame, 11 | void *srcCFrame, void *srcGoFrame, 12 | const char *mode, 13 | const char *sub_mode); 14 | 15 | extern bool LibyuvResampler_rotate( 16 | void *resampler, 17 | void *dstCFrame, void *dstGoFrame, 18 | void *srcCFrame, void *srcGoFrame, 19 | const char *mode); 20 | 21 | extern bool LibyuvResampler_toBgr( 22 | void *resampler, 23 | void *dstCFrame, void *dstGoFrame, 24 | void *srcCFrame, void *srcGoFrame); 25 | 26 | extern bool LibyuvResampler_toYuv420( 27 | void *resampler, 28 | void *dstCFrame, void *dstGoFrame, 29 | void *srcCFrame, void *srcGoFrame); 30 | */ 31 | import "C" 32 | import ( 33 | "unsafe" 34 | ) 35 | 36 | var LibyuvModes = struct { 37 | None subType 38 | Linear subType 39 | Bilinear subType 40 | Box subType 41 | }{ 42 | subType{"None"}, 43 | subType{"Linear"}, 44 | subType{"Bilinear"}, 45 | subType{"Box"}, 46 | } 47 | 48 | var LibyuvRotateModes = struct { 49 | Degree0 subType 50 | Degree90 subType 51 | Degree180 subType 52 | Degree270 subType 53 | }{ 54 | subType{"0"}, 55 | subType{"90"}, 56 | subType{"180"}, 57 | subType{"270"}, 58 | } 59 | 60 | type libyuvResampler resampler 61 | 62 | func (libyuvResampler *libyuvResampler) Close() { 63 | resamplerClose((*resampler)(libyuvResampler)) 64 | } 65 | 66 | func (libyuvResampler *libyuvResampler) ToBgr( 67 | dst IFrame, 68 | src IFrame) bool { 69 | dstGoFrame := dst.newGoRefFrame() 70 | srcGoFrame := src.newGoRefFrame() 71 | defer dst.deleteGoRefFrame(dstGoFrame) 72 | defer src.deleteGoRefFrame(srcGoFrame) 73 | return bool(C.LibyuvResampler_toBgr(unsafe.Pointer(libyuvResampler.cResampler), 74 | unsafe.Pointer(dst.refCFrame()), 75 | dstGoFrame, 76 | unsafe.Pointer(src.refCFrame()), 77 | srcGoFrame)) 78 | } 79 | 80 | func (libyuvResampler *libyuvResampler) ToYuv( 81 | dst IFrame, 82 | src IFrame) bool { 83 | dstGoFrame := dst.newGoRefFrame() 84 | srcGoFrame := src.newGoRefFrame() 85 | defer dst.deleteGoRefFrame(dstGoFrame) 86 | defer src.deleteGoRefFrame(srcGoFrame) 87 | return bool(C.LibyuvResampler_toYuv420(unsafe.Pointer(libyuvResampler.cResampler), 88 | unsafe.Pointer(dst.refCFrame()), 89 | dstGoFrame, 90 | unsafe.Pointer(src.refCFrame()), 91 | srcGoFrame)) 92 | } 93 | 94 | func (libyuvResampler *libyuvResampler) Resize( 95 | dst IFrame, 96 | src IFrame, 97 | mode subType, 98 | subMode subType) bool { 99 | dstGoFrame := dst.newGoRefFrame() 100 | srcGoFrame := src.newGoRefFrame() 101 | defer dst.deleteGoRefFrame(dstGoFrame) 102 | defer src.deleteGoRefFrame(srcGoFrame) 103 | cMode := C.CString(mode.value) 104 | defer C.free(unsafe.Pointer(cMode)) 105 | cSubMode := C.CString(subMode.value) 106 | defer C.free(unsafe.Pointer(cSubMode)) 107 | return bool(C.LibyuvResampler_resize(unsafe.Pointer(libyuvResampler.cResampler), 108 | unsafe.Pointer(dst.refCFrame()), 109 | dstGoFrame, 110 | unsafe.Pointer(src.refCFrame()), 111 | srcGoFrame, 112 | cMode, 113 | cSubMode)) 114 | } 115 | 116 | func (libyuvResampler *libyuvResampler) Rotate( 117 | dst IFrame, 118 | src IFrame, 119 | mode subType) bool { 120 | dstGoFrame := dst.newGoRefFrame() 121 | srcGoFrame := src.newGoRefFrame() 122 | defer dst.deleteGoRefFrame(dstGoFrame) 123 | defer src.deleteGoRefFrame(srcGoFrame) 124 | cMode := C.CString(mode.value) 125 | defer C.free(unsafe.Pointer(cMode)) 126 | return bool(C.LibyuvResampler_rotate(unsafe.Pointer(libyuvResampler.cResampler), 127 | unsafe.Pointer(dst.refCFrame()), 128 | dstGoFrame, 129 | unsafe.Pointer(src.refCFrame()), 130 | srcGoFrame, 131 | cMode)) 132 | } 133 | -------------------------------------------------------------------------------- /resamplerResizer.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | extern bool Resizer_resize( 9 | void *resampler, 10 | void *dstCFrame, void *dstGoFrame, 11 | void *srcCFrame, void *srcGoFrame, 12 | bool is_quick); 13 | */ 14 | import "C" 15 | import ( 16 | "unsafe" 17 | ) 18 | 19 | type resizeResampler resampler 20 | 21 | func (resizeResampler *resizeResampler) Close() { 22 | resamplerClose((*resampler)(resizeResampler)) 23 | } 24 | 25 | func (resizeResampler *resizeResampler) Resize( 26 | dst IFrame, 27 | src IFrame, 28 | isQuick bool) bool { 29 | dstGoFrame := dst.newGoRefFrame() 30 | srcGoFrame := src.newGoRefFrame() 31 | defer dst.deleteGoRefFrame(dstGoFrame) 32 | defer src.deleteGoRefFrame(srcGoFrame) 33 | return bool(C.Resizer_resize(unsafe.Pointer(resizeResampler.cResampler), 34 | unsafe.Pointer(dst.refCFrame()), 35 | dstGoFrame, 36 | unsafe.Pointer(src.refCFrame()), 37 | srcGoFrame, 38 | C.bool(isQuick))) 39 | } 40 | -------------------------------------------------------------------------------- /resamplerSoundtouch.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | extern void SoundtouchResampler_setRate(void *resampler, float newRate); 9 | extern void SoundtouchResampler_setTempo(void *resampler, float newTempo); 10 | extern void SoundtouchResampler_setRateChange(void *resampler, float newRate); 11 | extern void SoundtouchResampler_setTempoChange(void *resampler, float newTempo); 12 | extern void SoundtouchResampler_setPitch(void *resampler, float newPitch); 13 | extern void SoundtouchResampler_setPitchOctaves(void *resampler, float newPitch); 14 | extern void SoundtouchResampler_setPitchSemiTones(void *resampler, float newPitch); 15 | */ 16 | import "C" 17 | import ( 18 | "unsafe" 19 | ) 20 | 21 | type soundtouchResampler resampler 22 | 23 | // ResampleFrame リサンプルを実行 24 | func (soundtouchResampler *soundtouchResampler) ResampleFrame( 25 | frame IFrame, 26 | callback func(frame *Frame) bool) bool { 27 | return resamplerResampleFrame((*resampler)(soundtouchResampler), frame, callback) 28 | } 29 | 30 | // Close 閉じる 31 | func (soundtouchResampler *soundtouchResampler) Close() { 32 | resamplerClose((*resampler)(soundtouchResampler)) 33 | } 34 | 35 | func (soundtouchResampler *soundtouchResampler) SetRate(newRate float32) { 36 | C.SoundtouchResampler_setRate(unsafe.Pointer(soundtouchResampler.cResampler), C.float(newRate)) 37 | } 38 | 39 | func (soundtouchResampler *soundtouchResampler) SetTempo(newTempo float32) { 40 | C.SoundtouchResampler_setTempo(unsafe.Pointer(soundtouchResampler.cResampler), C.float(newTempo)) 41 | } 42 | 43 | func (soundtouchResampler *soundtouchResampler) SetRateChange(newRate float32) { 44 | C.SoundtouchResampler_setRateChange(unsafe.Pointer(soundtouchResampler.cResampler), C.float(newRate)) 45 | } 46 | 47 | func (soundtouchResampler *soundtouchResampler) SetTempoChange(newTempo float32) { 48 | C.SoundtouchResampler_setTempoChange(unsafe.Pointer(soundtouchResampler.cResampler), C.float(newTempo)) 49 | } 50 | 51 | func (soundtouchResampler *soundtouchResampler) SetPitch(newPitch float32) { 52 | C.SoundtouchResampler_setPitch(unsafe.Pointer(soundtouchResampler.cResampler), C.float(newPitch)) 53 | } 54 | 55 | func (soundtouchResampler *soundtouchResampler) SetPitchOctaves(newPitch float32) { 56 | C.SoundtouchResampler_setPitchOctaves(unsafe.Pointer(soundtouchResampler.cResampler), C.float(newPitch)) 57 | } 58 | 59 | func (soundtouchResampler *soundtouchResampler) SetPitchSemiTones(newPitch float32) { 60 | C.SoundtouchResampler_setPitchSemiTones(unsafe.Pointer(soundtouchResampler.cResampler), C.float(newPitch)) 61 | } 62 | -------------------------------------------------------------------------------- /resamplerSwscale.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | extern bool SwscaleResampler_resample(void *resampler, 9 | void *dstCFrame, void *dstGoFrame, 10 | void *srcCFrame, void *srcGoFrame); 11 | */ 12 | import "C" 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | type swscaleResampler resampler 18 | 19 | // SwscaleModes Swscaleのモードリスト 20 | var SwscaleModes = struct { 21 | X subType 22 | Area subType 23 | Sinc subType 24 | Point subType 25 | Gauss subType 26 | Spline subType 27 | Bicubic subType 28 | Lanczos subType 29 | Bilinear subType 30 | Bicublin subType 31 | FastBilinear subType 32 | }{ 33 | subType{"X"}, 34 | subType{"Area"}, 35 | subType{"Sinc"}, 36 | subType{"Point"}, 37 | subType{"Gauss"}, 38 | subType{"Spline"}, 39 | subType{"Bicubic"}, 40 | subType{"Lanczos"}, 41 | subType{"Bilinear"}, 42 | subType{"Bicublin"}, 43 | subType{"FastBilinear"}, 44 | } 45 | 46 | func (swscaleResampler *swscaleResampler) Close() { 47 | resamplerClose((*resampler)(swscaleResampler)) 48 | } 49 | 50 | func (swscaleResampler *swscaleResampler) Resample(dst IFrame, src IFrame) bool { 51 | dstGoFrame := dst.newGoRefFrame() 52 | srcGoFrame := src.newGoRefFrame() 53 | result := C.SwscaleResampler_resample( 54 | unsafe.Pointer(swscaleResampler.cResampler), 55 | unsafe.Pointer(dst.refCFrame()), 56 | dstGoFrame, 57 | unsafe.Pointer(src.refCFrame()), 58 | srcGoFrame) 59 | dst.deleteGoRefFrame(dstGoFrame) 60 | src.deleteGoRefFrame(srcGoFrame) 61 | return bool(result) 62 | } 63 | -------------------------------------------------------------------------------- /test/convert_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "encoding/hex" 5 | "math" 6 | "testing" 7 | 8 | "github.com/taktod/ttLibGo" 9 | ) 10 | 11 | func checkEq(t *testing.T, targetHex string, frame ttLibGo.IFrame) { 12 | targetArray := []byte(targetHex) 13 | frame.GetBinaryBuffer(func(data []byte) bool { 14 | l := len(data) 15 | l2 := len(targetArray) 16 | if l > l2 { 17 | l = l2 18 | } 19 | err := false 20 | for i := 0; i < l; i++ { 21 | if math.Abs(float64(data[i])-float64(targetArray[i])) > 10 { 22 | err = true 23 | } 24 | } 25 | if err { 26 | t.Error(hex.Dump(targetArray)) 27 | t.Error(hex.Dump(data)) 28 | } 29 | return true 30 | }) 31 | } 32 | 33 | func scaleYuvPlanar(t *testing.T, targetCall func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool) { 34 | t.Log("scaleYuvPlanar") 35 | src := ttLibGo.Yuv420.FromBinary([]byte(""+ 36 | "\x00\x00\x80\x80"+ 37 | "\x00\x00\x40\x20"+ 38 | "\xFF\xFF"+ 39 | "\x80\xF0"), 40 | 12, 1, 0, 1000, ttLibGo.Yuv420Types.Yuv420, 4, 2) 41 | defer src.Close() 42 | dst := ttLibGo.Yuv420.FromBinary([]byte(""+ 43 | "\x00\x00\x00\x00\x00\x00\x00\x00"+ 44 | "\x00\x00\x00\x00\x00\x00\x00\x00"+ 45 | "\x00\x00\x00\x00"+ 46 | "\x00\x00\x00\x00"), 47 | 24, 1, 0, 1000, ttLibGo.Yuv420Types.Yuv420, 8, 2) 48 | defer dst.Close() 49 | targetCall(dst, src) 50 | checkEq(t, ""+ 51 | "\x00\x00\x00\x20\x60\x80\x80\x80"+ 52 | "\x00\x00\x00\x10\x30\x38\x28\x20"+ 53 | "\xFF\xFF\xFF\xFF"+ 54 | "\x80\x80\xF0\xF0", 55 | dst) 56 | } 57 | 58 | func scaleYuvPlanarClip(t *testing.T, targetCall func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool) { 59 | t.Log("scaleYuvPlanarClip") 60 | src := ttLibGo.Yuv420.FromBinary([]byte(""+ 61 | "\x00\x00\x80\x80"+ 62 | "\x00\x00\x40\x20"+ 63 | "\xFF\xFF"+ 64 | "\x80\xF0"), 65 | 12, 1, 0, 1000, ttLibGo.Yuv420Types.Yuv420, 4, 2) 66 | defer src.Close() 67 | dst := ttLibGo.Yuv420.FromBinary([]byte(""+ 68 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"+ 69 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"+ 70 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"+ 71 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"+ 72 | "\xFF\xFF\xFF\xFF\xFF"+ 73 | "\xFF\xFF\xFF\xFF\xFF"+ 74 | "\xFF\xFF\xFF\xFF\xFF"+ 75 | "\xFF\xFF\xFF\xFF\xFF"), 76 | 60, 1, 0, 1000, ttLibGo.Yuv420Types.Yuv420, 10, 4) 77 | defer dst.Close() 78 | ydst := ttLibGo.Yuv420.Cast(dst) 79 | ydst.Width = 8 80 | ydst.Height = 2 81 | yDataPos := ydst.YData 82 | ydst.YData = uintptr(uint64(ydst.YData) + uint64(ydst.YStride) + 1) 83 | targetCall(ydst, src) 84 | ydst.Width = 10 85 | ydst.Height = 4 86 | ydst.YData = yDataPos 87 | checkEq(t, ""+ 88 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"+ 89 | "\xFF\x00\x00\x00\x20\x60\x80\x80\x80\xFF"+ 90 | "\xFF\x00\x00\x00\x10\x30\x38\x28\x20\xFF"+ 91 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"+ 92 | "\xFF\xFF\xFF\xFF\xFF"+ 93 | "\xFF\xFF\xFF\xFF\xFF"+ 94 | "\x80\x80\xF0\xF0\xFF"+ 95 | "\xFF\xFF\xFF\xFF\xFF", 96 | ydst) 97 | } 98 | 99 | func yuvPlanarToBgra(t *testing.T, targetCall func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool) { 100 | t.Log("yuvPlanarToBgra") 101 | src := ttLibGo.Yuv420.FromBinary([]byte(""+ 102 | "\x00\x00\x80\x80"+ 103 | "\x00\x00\x40\x20"+ 104 | "\xFF\xFF"+ 105 | "\x80\xF0"), 106 | 12, 1, 0, 1000, ttLibGo.Yuv420Types.Yuv420, 4, 2) 107 | defer src.Close() 108 | dst := ttLibGo.Bgr.FromBinary([]byte(""+ 109 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+ 110 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), 111 | 32, 1, 0, 1000, ttLibGo.BgrTypes.Bgra, 4, 2, 16) 112 | defer dst.Close() 113 | targetCall(dst, src) 114 | checkEq(t, ""+ 115 | "\xEB\x00\x00\xFF\xEB\x00\x00\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF"+ 116 | "\xEB\x00\x00\xFF\xEB\x00\x00\xFF\xFF\x00\xEA\xFF\xFF\x00\xC5\xFF", 117 | dst) 118 | } 119 | 120 | func yuvPlanarToAbgr(t *testing.T, targetCall func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool) { 121 | t.Log("yuvPlanarToAbgr") 122 | src := ttLibGo.Yuv420.FromBinary([]byte(""+ 123 | "\x00\x00\x80\x80"+ 124 | "\x00\x00\x40\x20"+ 125 | "\xFF\xFF"+ 126 | "\x80\xF0"), 127 | 12, 1, 0, 1000, ttLibGo.Yuv420Types.Yuv420, 4, 2) 128 | defer src.Close() 129 | dst := ttLibGo.Bgr.FromBinary([]byte(""+ 130 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+ 131 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), 132 | 32, 1, 0, 1000, ttLibGo.BgrTypes.Abgr, 4, 2, 16) 133 | defer dst.Close() 134 | targetCall(dst, src) 135 | checkEq(t, ""+ 136 | "\xFF\xEB\x00\x00\xFF\xEB\x00\x00\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF"+ 137 | "\xFF\xEB\x00\x00\xFF\xEB\x00\x00\xFF\xFF\x00\xEA\xFF\xFF\x00\xC5", 138 | dst) 139 | } 140 | 141 | func yuvPlanarToRgba(t *testing.T, targetCall func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool) { 142 | t.Log("yuvPlanarToRgba") 143 | src := ttLibGo.Yuv420.FromBinary([]byte(""+ 144 | "\x00\x00\x80\x80"+ 145 | "\x00\x00\x40\x20"+ 146 | "\xFF\xFF"+ 147 | "\x80\xF0"), 148 | 12, 1, 0, 1000, ttLibGo.Yuv420Types.Yuv420, 4, 2) 149 | defer src.Close() 150 | dst := ttLibGo.Bgr.FromBinary([]byte(""+ 151 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"+ 152 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), 153 | 32, 1, 0, 1000, ttLibGo.BgrTypes.Rgba, 4, 2, 16) 154 | defer dst.Close() 155 | targetCall(dst, src) 156 | checkEq(t, ""+ 157 | "\x00\x00\xEB\xFF\x00\x00\xEB\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF"+ 158 | "\x00\x00\xEB\xFF\x00\x00\xEB\xFF\xEA\x00\xFF\xFF\xC5\x00\xFF\xFF", 159 | dst) 160 | } 161 | 162 | func TestSwscale(t *testing.T) { 163 | { 164 | swscale := ttLibGo.Resamplers.Swscale(ttLibGo.FrameTypes.Yuv420, ttLibGo.Yuv420Types.Yuv420, 4, 2, 165 | ttLibGo.FrameTypes.Yuv420, ttLibGo.Yuv420Types.Yuv420, 8, 2, ttLibGo.SwscaleModes.FastBilinear) 166 | defer swscale.Close() 167 | scaleYuvPlanar(t, swscale.Resample) 168 | } 169 | { 170 | swscale := ttLibGo.Resamplers.Swscale(ttLibGo.FrameTypes.Yuv420, ttLibGo.Yuv420Types.Yuv420, 4, 2, 171 | ttLibGo.FrameTypes.Yuv420, ttLibGo.Yuv420Types.Yuv420, 8, 2, ttLibGo.SwscaleModes.FastBilinear) 172 | defer swscale.Close() 173 | scaleYuvPlanarClip(t, swscale.Resample) 174 | } 175 | } 176 | 177 | func TestLibyuv(t *testing.T) { 178 | libyuv := ttLibGo.Resamplers.Libyuv() 179 | defer libyuv.Close() 180 | { 181 | scaleYuvPlanar(t, func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool { 182 | return libyuv.Resize(dst, src, ttLibGo.LibyuvModes.Linear, ttLibGo.LibyuvModes.None) 183 | }) 184 | } 185 | { 186 | scaleYuvPlanarClip(t, func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool { 187 | return libyuv.Resize(dst, src, ttLibGo.LibyuvModes.Linear, ttLibGo.LibyuvModes.None) 188 | }) 189 | } 190 | yuvPlanarToBgra(t, libyuv.ToBgr) 191 | yuvPlanarToAbgr(t, libyuv.ToBgr) 192 | yuvPlanarToRgba(t, libyuv.ToBgr) 193 | } 194 | 195 | func TestImage(t *testing.T) { 196 | image := ttLibGo.Resamplers.Image() 197 | defer image.Close() 198 | yuvPlanarToBgra(t, image.ToBgr) 199 | yuvPlanarToAbgr(t, image.ToBgr) 200 | yuvPlanarToRgba(t, image.ToBgr) 201 | } 202 | 203 | func TestResize(t *testing.T) { 204 | /* resize := ttLibGo.Resamplers.Resize() 205 | defer resize.Close() 206 | scaleYuvPlanar(t, func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool { 207 | return resize.Resize(dst, src, false) 208 | }) 209 | scaleYuvPlanarClip(t, func(dst ttLibGo.IFrame, src ttLibGo.IFrame) bool { 210 | return resize.Resize(dst, src, false) 211 | })*/ 212 | } 213 | -------------------------------------------------------------------------------- /test/decoder_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | 8 | "github.com/taktod/ttLibGo" 9 | ) 10 | 11 | func decodeBody(t *testing.T, targetFile string, reader ttLibGo.IReader, targetType interface{}, decoder ttLibGo.IDecoder) { 12 | t.Log(fmt.Sprintf("decoder:%v targetFrame:%v", decoder, targetType)) 13 | count := 0 14 | in, err := os.Open(targetFile) 15 | if err != nil { 16 | panic(err) 17 | } 18 | defer reader.Close() 19 | defer decoder.Close() 20 | for { 21 | buffer := make([]byte, 65536) 22 | length, err := in.Read(buffer) 23 | if length == 0 { 24 | break 25 | } 26 | if err != nil { 27 | panic(err) 28 | } 29 | if !reader.ReadFrame( 30 | buffer, 31 | uint64(length), 32 | func(frame *ttLibGo.Frame) bool { 33 | if frame.Type == targetType { 34 | decoder.DecodeFrame(frame, func(frame *ttLibGo.Frame) bool { 35 | count++ 36 | return true 37 | }) 38 | } 39 | return true 40 | }) { 41 | t.Errorf("読み込み失敗しました") 42 | return 43 | } 44 | if count > 5 { 45 | return 46 | } 47 | if length < 65536 { 48 | break 49 | } 50 | } 51 | t.Error(fmt.Sprintf("decodeデータ数が規定に達しませんでした。%d", count)) 52 | } 53 | 54 | func TestAvcodecVideoDecoder(t *testing.T) { 55 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360)) 56 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.speex.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Flv1, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.Flv1, 640, 360)) 57 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp6.mp3.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Vp6, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.Vp6, 640, 360)) 58 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.adpcmimawav.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Jpeg, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.Jpeg, 640, 360)) 59 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.png.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Png, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.Png, 640, 360)) 60 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.H265, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H265, 640, 360)) 61 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.aac.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360)) 62 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.theora.speex.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Theora, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.Theora, 640, 360)) 63 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp8.vorbis.webm", ttLibGo.Readers.Webm(), ttLibGo.FrameTypes.Vp8, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.Vp8, 640, 360)) 64 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp9.opus.webm", ttLibGo.Readers.Webm(), ttLibGo.FrameTypes.Vp9, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.Vp9, 640, 360)) 65 | } 66 | 67 | func TestAvcodecAudioDecoder(t *testing.T) { 68 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Aac, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.Aac, 44100, 2)) 69 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.nellymoser.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Nellymoser, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.Nellymoser, 44100, 1)) 70 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.pcm_alaw.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.PcmAlaw, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.PcmAlaw, 8000, 1)) 71 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.pcm_mulaw.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.PcmMulaw, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.PcmMulaw, 8000, 1)) 72 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.speex.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Speex, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.Speex, 16000, 1)) 73 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp6.mp3.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Mp3, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.Mp3, 44100, 2)) 74 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.adpcmimawav.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.AdpcmImaWav, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.AdpcmImaWav, 44100, 2)) 75 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Opus, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.Opus, 48000, 2)) 76 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.vorbis.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Vorbis, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.Vorbis, 44100, 2)) 77 | } 78 | 79 | func TestJpegDecoder(t *testing.T) { 80 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.adpcmimawav.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Jpeg, ttLibGo.Decoders.Jpeg()) 81 | } 82 | 83 | func TestOpenh264Decoder(t *testing.T) { 84 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.Openh264()) 85 | } 86 | 87 | func TestOpusDecoder(t *testing.T) { 88 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Opus, func() ttLibGo.IDecoder { 89 | op := ttLibGo.Decoders.Opus(48000, 2) 90 | op.SetCodecControl(ttLibGo.OpusDecoderControls.SetPhaseInversionDisabled, true) 91 | sampleRate := op.GetCodecControl(ttLibGo.OpusDecoderControls.GetSampleRate) 92 | if sampleRate != 48000 { 93 | t.Error("failed to ref sampleRate") 94 | } 95 | fmt.Println(sampleRate) 96 | return op 97 | }()) 98 | // decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Opus, ttLibGo.Decoders.Opus(48000, 2)) 99 | } 100 | 101 | func TestPngDecoder(t *testing.T) { 102 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.png.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Png, ttLibGo.Decoders.Png()) 103 | } 104 | 105 | func TestSpeexDecoder(t *testing.T) { 106 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.speex.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Speex, ttLibGo.Decoders.Speex(16000, 1)) 107 | } 108 | 109 | func TestTheoraDecoder(t *testing.T) { 110 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.theora.speex.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Theora, ttLibGo.Decoders.Theora()) 111 | } 112 | 113 | func TestVorbisDecoder(t *testing.T) { 114 | decodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.vorbis.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Vorbis, ttLibGo.Decoders.Vorbis()) 115 | } 116 | -------------------------------------------------------------------------------- /test/encoder_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | 8 | "github.com/taktod/ttLibGo" 9 | ) 10 | 11 | func encodeBody(t *testing.T, targetFile string, reader ttLibGo.IReader, targetType interface{}, decoder ttLibGo.IDecoder, encoder ttLibGo.IEncoder) { 12 | t.Log(fmt.Sprintf("encoder:%v", encoder)) 13 | count := 0 14 | in, err := os.Open(targetFile) 15 | if err != nil { 16 | panic(err) 17 | } 18 | defer reader.Close() 19 | defer decoder.Close() 20 | defer encoder.Close() 21 | for { 22 | buffer := make([]byte, 65536) 23 | length, err := in.Read(buffer) 24 | if length == 0 { 25 | break 26 | } 27 | if err != nil { 28 | panic(err) 29 | } 30 | if !reader.ReadFrame( 31 | buffer, 32 | uint64(length), 33 | func(frame *ttLibGo.Frame) bool { 34 | if frame.Type == targetType { 35 | decoder.DecodeFrame(frame, func(frame *ttLibGo.Frame) bool { 36 | return encoder.EncodeFrame(frame, func(frame *ttLibGo.Frame) bool { 37 | count++ 38 | return true 39 | }) 40 | }) 41 | } 42 | return true 43 | }) { 44 | t.Errorf("読み込み失敗しました") 45 | return 46 | } 47 | if count > 5 { 48 | return 49 | } 50 | if length < 65536 { 51 | break 52 | } 53 | } 54 | t.Error(fmt.Sprintf("encodeデータ数が規定に達しませんでした。%d", count)) 55 | } 56 | 57 | func TestFdkaacEncoder(t *testing.T) { 58 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Opus, ttLibGo.Decoders.Opus(48000, 2), func() ttLibGo.IEncoder { 59 | fdk := ttLibGo.Encoders.Fdkaac(ttLibGo.FdkAacTypes.AotAacLC, 48000, 2, 48000) 60 | fdk.SetBitrate(96000) 61 | return fdk 62 | }()) 63 | } 64 | func TestJpegEncoder(t *testing.T) { 65 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), func() ttLibGo.IEncoder { 66 | jpeg := ttLibGo.Encoders.Jpeg(640, 360, 90) 67 | jpeg.SetQuality(85) 68 | return jpeg 69 | }()) 70 | } 71 | 72 | func TestOpenh264Encoder(t *testing.T) { 73 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 74 | func() ttLibGo.IEncoder { 75 | o := ttLibGo.Encoders.Openh264(640, 360, nil, nil) 76 | o.SetIDRInterval(15) 77 | return o 78 | }()) 79 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 80 | ttLibGo.Encoders.Openh264(640, 360, []ttLibGo.Openh264Data{ 81 | ttLibGo.Openh264Params.IMinQp(4), 82 | ttLibGo.Openh264Params.IMaxQp(51), 83 | }, nil)) 84 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 85 | ttLibGo.Encoders.Openh264(640, 360, []ttLibGo.Openh264Data{ 86 | ttLibGo.Openh264Params.IMinQp(4), 87 | ttLibGo.Openh264Params.IMaxQp(51), 88 | ttLibGo.Openh264Params.ITargetBitrate(300000), 89 | ttLibGo.Openh264Params.IMaxBitrate(310000), 90 | }, [][]ttLibGo.Openh264Data{ 91 | []ttLibGo.Openh264Data{ 92 | ttLibGo.Openh264SpatialParams.ISpatialBitrate(300000), 93 | ttLibGo.Openh264SpatialParams.IMaxSpatialBitrate(310000), 94 | ttLibGo.Openh264SpatialParams.SliceArgument.SliceMode.SmSingleSLICE, 95 | }, 96 | })) 97 | } 98 | 99 | func TestOpusEncoder(t *testing.T) { 100 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Opus, ttLibGo.Decoders.Opus(48000, 2), func() ttLibGo.IEncoder { 101 | o := ttLibGo.Encoders.Opus(48000, 2, 480) 102 | first_bitrate := o.GetCodecControl(ttLibGo.OpusEncoderControls.GetBitrate) 103 | o.SetCodecControl(ttLibGo.OpusEncoderControls.SetBitrate, 96000) 104 | bitrate := o.GetCodecControl(ttLibGo.OpusEncoderControls.GetBitrate) 105 | if first_bitrate == bitrate || bitrate != 96000 { 106 | t.Error(fmt.Sprintf("first_bitrate:%d bitrate:%d", first_bitrate, bitrate)) 107 | } 108 | return o 109 | }()) 110 | } 111 | 112 | func TestSpeexEncoder(t *testing.T) { 113 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.speex.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Speex, ttLibGo.Decoders.Speex(16000, 1), ttLibGo.Encoders.Speex(16000, 1, 8)) 114 | } 115 | 116 | func TestTheoraEncoder(t *testing.T) { 117 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), ttLibGo.Encoders.Theora(640, 360, 25, 320000, 15)) 118 | } 119 | 120 | func TestVorbisEncoder(t *testing.T) { 121 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Opus, ttLibGo.Decoders.Opus(48000, 2), ttLibGo.Encoders.Vorbis(48000, 2)) 122 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Aac, ttLibGo.Decoders.AvcodecAudio(ttLibGo.FrameTypes.Aac, 44100, 2), ttLibGo.Encoders.Vorbis(44100, 2)) 123 | } 124 | 125 | func TestX264Encoder(t *testing.T) { 126 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 127 | ttLibGo.Encoders.X264(640, 360, "", "", "", nil)) 128 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 129 | ttLibGo.Encoders.X264(640, 360, "veryfast", "zerolatency", "main", nil)) 130 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 131 | ttLibGo.Encoders.X264(640, 360, "veryfast", "zerolatency", "main", []ttLibGo.KeyValue{ 132 | {"open-gop", "1"}, 133 | {"threads", "1"}, 134 | {"merange", "16"}, 135 | {"qcomp", "0.6"}, 136 | {"ip-factor", "0.71"}, 137 | {"bitrate", "300"}, 138 | {"qp", "21"}, 139 | {"crf", "23"}, 140 | {"crf-max", "23"}, 141 | {"fps", "30/1"}, 142 | {"keyint", "150"}, 143 | {"keyint-min", "150"}, 144 | {"bframes", "3"}, 145 | {"vbv-maxrate", "0"}, 146 | {"vbv-bufsize", "1024"}, 147 | {"qp-max", "40"}, 148 | {"qp-min", "21"}, 149 | {"qp-step", "4"}, 150 | })) 151 | } 152 | 153 | func TestX265Encoder(t *testing.T) { 154 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 155 | ttLibGo.Encoders.X265(640, 360, "", "", "", nil)) 156 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 157 | ttLibGo.Encoders.X265(640, 360, "veryfast", "zerolatency", "main", nil)) 158 | encodeBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360), 159 | ttLibGo.Encoders.X265(640, 360, "veryfast", "zerolatency", "main", []ttLibGo.KeyValue{ 160 | {"bitrate", "300"}, 161 | {"qpmax", "40"}, 162 | {"qpmin", "21"}, 163 | })) 164 | } 165 | -------------------------------------------------------------------------------- /test/reader_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | 8 | "github.com/taktod/ttLibGo" 9 | ) 10 | 11 | func readerBody(t *testing.T, targetFile string, reader ttLibGo.IReader, type1 interface{}, type2 interface{}) { 12 | t.Log(fmt.Sprintf("reader:%v %v %v", reader, type1, type2)) 13 | type1Count := 0 14 | type2Count := 0 15 | in, err := os.Open(targetFile) 16 | if err != nil { 17 | panic(err) 18 | } 19 | defer reader.Close() 20 | for { 21 | buffer := make([]byte, 65536) 22 | length, err := in.Read(buffer) 23 | if length == 0 { 24 | break 25 | } 26 | if err != nil { 27 | panic(err) 28 | } 29 | if !reader.ReadFrame( 30 | buffer, 31 | uint64(length), 32 | func(frame *ttLibGo.Frame) bool { 33 | if frame.Type == type1 { 34 | type1Count++ 35 | } 36 | if frame.Type == type2 { 37 | type2Count++ 38 | } 39 | return true 40 | }) { 41 | t.Errorf("読み込み失敗しました") 42 | return 43 | } 44 | if length < 65536 { 45 | break 46 | } 47 | } 48 | if type1Count == 0 { 49 | t.Error(fmt.Sprintf("%vが取得できませんでした", type1)) 50 | } 51 | if type1 != type2 && type2Count == 0 { 52 | t.Error(fmt.Sprintf("%vが取得できませんでした", type2)) 53 | } 54 | } 55 | 56 | func TestFlvReader(t *testing.T) { 57 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.nellymoser.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.Nellymoser) 58 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.pcm_alaw.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.PcmAlaw) 59 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.pcm_mulaw.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.PcmMulaw) 60 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.speex.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.Speex) 61 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 62 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp6.mp3.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.Vp6, ttLibGo.FrameTypes.Mp3) 63 | } 64 | 65 | func TestMkvReader(t *testing.T) { 66 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 67 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 68 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.adpcmimawav.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.AdpcmImaWav) 69 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.pcms16.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.PcmS16) 70 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Opus, ttLibGo.FrameTypes.Opus) 71 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.png.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Png, ttLibGo.FrameTypes.Png) 72 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.theora.speex.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Theora, ttLibGo.FrameTypes.Speex) 73 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vorbis.mkv", ttLibGo.Readers.Mkv(), ttLibGo.FrameTypes.Vorbis, ttLibGo.FrameTypes.Vorbis) 74 | } 75 | 76 | func TestWebmReader(t *testing.T) { 77 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp8.vorbis.webm", ttLibGo.Readers.Webm(), ttLibGo.FrameTypes.Vp8, ttLibGo.FrameTypes.Vorbis) 78 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp9.opus.webm", ttLibGo.Readers.Webm(), ttLibGo.FrameTypes.Vp9, ttLibGo.FrameTypes.Opus) 79 | } 80 | 81 | func TestMp4Reader(t *testing.T) { 82 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.frag.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 83 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 84 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.mp4box.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 85 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.aac.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 86 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.boxed.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 87 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 88 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.frag.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 89 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 90 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.mp4box.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 91 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.vorbis.frag.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.Vorbis) 92 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.vorbis.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.Vorbis) 93 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.vorbis.mp4box.mp4", ttLibGo.Readers.Mp4(), ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.Vorbis) 94 | } 95 | 96 | func TestMpegtsReader(t *testing.T) { 97 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.10sec.ts", ttLibGo.Readers.Mpegts(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 98 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.ts", ttLibGo.Readers.Mpegts(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 99 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.mp3.ts", ttLibGo.Readers.Mpegts(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 100 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.aac.ts", ttLibGo.Readers.Mpegts(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 101 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.10sec.ts", ttLibGo.Readers.Mpegts(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 102 | readerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.ts", ttLibGo.Readers.Mpegts(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 103 | } 104 | 105 | /* 106 | func TestHoge(t *testing.T) { 107 | readerBody(t, os.Getenv("HOME")+"/Documents/node/ttLibJsGyp/js/target.flv", ttLibGo.Readers.Flv(), ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 108 | } 109 | */ 110 | -------------------------------------------------------------------------------- /test/writer_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | 8 | "github.com/taktod/ttLibGo" 9 | ) 10 | 11 | func writerBody(t *testing.T, targetFile string, reader ttLibGo.IReader, writer ttLibGo.IWriter) { 12 | t.Log(fmt.Sprintf("writer:%v", writer)) 13 | writeCount := 0 14 | in, err := os.Open(targetFile) 15 | if err != nil { 16 | panic(err) 17 | } 18 | defer reader.Close() 19 | defer writer.Close() 20 | for { 21 | buffer := make([]byte, 65536) 22 | length, err := in.Read(buffer) 23 | if length == 0 { 24 | break 25 | } 26 | if err != nil { 27 | panic(err) 28 | } 29 | if !reader.ReadFrame( 30 | buffer, 31 | uint64(length), 32 | func(frame *ttLibGo.Frame) bool { 33 | return writer.WriteFrame(frame, func(data []byte) bool { 34 | writeCount += len(data) 35 | return true 36 | }) 37 | }) { 38 | t.Errorf("読み込み失敗しました") 39 | return 40 | } 41 | if length < 65536 { 42 | break 43 | } 44 | } 45 | if writeCount < 100 { 46 | t.Error(fmt.Sprintf("出力が小さすぎます:size:%d", writeCount)) 47 | } 48 | } 49 | 50 | func TestFlvWriter(t *testing.T) { 51 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.nellymoser.flv", ttLibGo.Readers.Flv(), ttLibGo.Writers.Flv(ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.Nellymoser)) 52 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.pcm_alaw.flv", ttLibGo.Readers.Flv(), ttLibGo.Writers.Flv(ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.PcmAlaw)) 53 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.pcm_mulaw.flv", ttLibGo.Readers.Flv(), ttLibGo.Writers.Flv(ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.PcmMulaw)) 54 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.flv1.speex.flv", ttLibGo.Readers.Flv(), ttLibGo.Writers.Flv(ttLibGo.FrameTypes.Flv1, ttLibGo.FrameTypes.Speex)) 55 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.flv", ttLibGo.Readers.Flv(), ttLibGo.Writers.Flv(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac)) 56 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp6.mp3.flv", ttLibGo.Readers.Flv(), ttLibGo.Writers.Flv(ttLibGo.FrameTypes.Vp6, ttLibGo.FrameTypes.Mp3)) 57 | } 58 | 59 | func TestMkvWriter(t *testing.T) { 60 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.mkv", ttLibGo.Readers.Mkv(), ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac)) 61 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.mkv", ttLibGo.Readers.Mkv(), func() ttLibGo.IWriter { 62 | writer := ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 63 | writer.Mode = ttLibGo.WriterModes.EnableDts 64 | return writer 65 | }()) 66 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.adpcmimawav.mkv", ttLibGo.Readers.Mkv(), ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.AdpcmImaWav)) 67 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.pcms16.mkv", ttLibGo.Readers.Mkv(), ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.PcmS16)) 68 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.opus.mkv", ttLibGo.Readers.Mkv(), ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.Opus)) 69 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.png.mkv", ttLibGo.Readers.Mkv(), ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.Png)) 70 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.theora.speex.mkv", ttLibGo.Readers.Mkv(), ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.Theora, ttLibGo.FrameTypes.Speex)) 71 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vorbis.mkv", ttLibGo.Readers.Mkv(), ttLibGo.Writers.Mkv(ttLibGo.FrameTypes.Vorbis)) 72 | } 73 | 74 | func TestWebmWriter(t *testing.T) { 75 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp8.vorbis.webm", ttLibGo.Readers.Webm(), ttLibGo.Writers.Webm(ttLibGo.FrameTypes.Vp8, ttLibGo.FrameTypes.Vorbis)) 76 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.vp9.opus.webm", ttLibGo.Readers.Webm(), ttLibGo.Writers.Webm(ttLibGo.FrameTypes.Vp9, ttLibGo.FrameTypes.Opus)) 77 | } 78 | 79 | func TestMp4Writer(t *testing.T) { 80 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.frag.mp4", ttLibGo.Readers.Mp4(), ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac)) 81 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.mp4", ttLibGo.Readers.Mp4(), ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac)) 82 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.mp4box.mp4", ttLibGo.Readers.Mp4(), ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac)) 83 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.aac.mp4", ttLibGo.Readers.Mp4(), func() ttLibGo.IWriter { 84 | writer := ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 85 | writer.Mode = ttLibGo.WriterModes.EnableDts 86 | return writer 87 | }()) 88 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.boxed.mp4", ttLibGo.Readers.Mp4(), func() ttLibGo.IWriter { 89 | writer := ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 90 | writer.Mode = ttLibGo.WriterModes.EnableDts 91 | return writer 92 | }()) 93 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.mp4", ttLibGo.Readers.Mp4(), func() ttLibGo.IWriter { 94 | writer := ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 95 | writer.Mode = ttLibGo.WriterModes.EnableDts 96 | return writer 97 | }()) 98 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.frag.mp4", ttLibGo.Readers.Mp4(), func() ttLibGo.IWriter { 99 | writer := ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 100 | writer.Mode = ttLibGo.WriterModes.EnableDts 101 | return writer 102 | }()) 103 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.mp4", ttLibGo.Readers.Mp4(), func() ttLibGo.IWriter { 104 | writer := ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 105 | writer.Mode = ttLibGo.WriterModes.EnableDts 106 | return writer 107 | }()) 108 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h265.mp3.mp4box.mp4", ttLibGo.Readers.Mp4(), func() ttLibGo.IWriter { 109 | writer := ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.H265, ttLibGo.FrameTypes.Mp3) 110 | writer.Mode = ttLibGo.WriterModes.EnableDts 111 | return writer 112 | }()) 113 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.vorbis.frag.mp4", ttLibGo.Readers.Mp4(), ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.Vorbis)) 114 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.vorbis.mp4", ttLibGo.Readers.Mp4(), ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.Vorbis)) 115 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.mjpeg.vorbis.mp4box.mp4", ttLibGo.Readers.Mp4(), ttLibGo.Writers.Mp4(ttLibGo.FrameTypes.Jpeg, ttLibGo.FrameTypes.Vorbis)) 116 | } 117 | 118 | func TestMpegtsWriter(t *testing.T) { 119 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.10sec.ts", ttLibGo.Readers.Mpegts(), ttLibGo.Writers.Mpegts(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac)) 120 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.aac.ts", ttLibGo.Readers.Mpegts(), ttLibGo.Writers.Mpegts(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac)) 121 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264.mp3.ts", ttLibGo.Readers.Mpegts(), ttLibGo.Writers.Mpegts(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3)) 122 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.aac.ts", ttLibGo.Readers.Mpegts(), func() ttLibGo.IWriter { 123 | writer := ttLibGo.Writers.Mpegts(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Aac) 124 | writer.Mode = ttLibGo.WriterModes.EnableDts 125 | return writer 126 | }()) 127 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.10sec.ts", ttLibGo.Readers.Mpegts(), func() ttLibGo.IWriter { 128 | writer := ttLibGo.Writers.Mpegts(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 129 | writer.Mode = ttLibGo.WriterModes.EnableDts 130 | return writer 131 | }()) 132 | writerBody(t, os.Getenv("HOME")+"/tools/data/source/test.h264b.mp3.ts", ttLibGo.Readers.Mpegts(), func() ttLibGo.IWriter { 133 | writer := ttLibGo.Writers.Mpegts(ttLibGo.FrameTypes.H264, ttLibGo.FrameTypes.Mp3) 134 | writer.Mode = ttLibGo.WriterModes.EnableDts 135 | return writer 136 | }()) 137 | } 138 | -------------------------------------------------------------------------------- /test/x265check_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | 8 | "github.com/taktod/ttLibGo" 9 | ) 10 | 11 | func TsTestX265EncodeDataCheck(t *testing.T) { 12 | in, err := os.Open(os.Getenv("HOME") + "/tools/data/source/test.h264.aac.flv") 13 | if err != nil { 14 | panic(err) 15 | } 16 | counter := 0 17 | frameTypes := ttLibGo.FrameTypes 18 | reader := ttLibGo.Readers.Flv() 19 | defer reader.Close() 20 | decoder := ttLibGo.Decoders.AvcodecVideo(frameTypes.H264, 640, 360) 21 | defer decoder.Close() 22 | encoder := ttLibGo.Encoders.X265(640, 360, "", "", "", nil) 23 | defer encoder.Close() 24 | decoder2 := ttLibGo.Decoders.AvcodecVideo(frameTypes.H265, 640, 360) 25 | defer decoder2.Close() 26 | encoder2 := ttLibGo.Encoders.Jpeg(640, 360, 90) 27 | defer encoder2.Close() 28 | for { 29 | buffer := make([]byte, 65536) 30 | length, err := in.Read(buffer) 31 | if length == 0 { 32 | break 33 | } 34 | if err != nil { 35 | panic(err) 36 | } 37 | if !reader.ReadFrame(buffer, uint64(length), func(frame *ttLibGo.Frame) bool { 38 | if frame.Type != frameTypes.H264 { 39 | return true 40 | } 41 | return decoder.DecodeFrame(frame, func(frame *ttLibGo.Frame) bool { 42 | if counter%5 == 0 { 43 | encoder.ForceNextFrameType(ttLibGo.X265EncoderFrameTypes.IDR) 44 | } else { 45 | encoder.ForceNextFrameType(ttLibGo.X265EncoderFrameTypes.P) 46 | } 47 | return encoder.EncodeFrame(frame, func(frame *ttLibGo.Frame) bool { 48 | fmt.Println(ttLibGo.H265.Cast(frame)) 49 | return decoder2.DecodeFrame(frame, func(frame *ttLibGo.Frame) bool { 50 | return encoder2.EncodeFrame(frame, func(frame *ttLibGo.Frame) bool { 51 | counter++ 52 | /* return frame.GetBinaryBuffer(func(buf []byte) bool { 53 | file := fmt.Sprintf("out%d.jpeg", counter) 54 | out, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE, 0666) 55 | if err != nil { 56 | panic(err) 57 | } 58 | out.Write(buf) 59 | counter++ 60 | return true 61 | })*/ 62 | return true 63 | }) 64 | }) 65 | }) 66 | }) 67 | }) { 68 | t.Error("読み込み失敗") 69 | return 70 | } 71 | if length < 65536 { 72 | break 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /test/yuvclip_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/taktod/ttLibGo" 8 | ) 9 | 10 | func TsTestYuvClip(t *testing.T) { 11 | t.Log("h264 / aac") 12 | in, err := os.Open(os.Getenv("HOME") + "/tools/data/source/test.h264.aac.flv") 13 | if err != nil { 14 | panic(err) 15 | } 16 | // counter := 1 17 | decoder := ttLibGo.Decoders.AvcodecVideo(ttLibGo.FrameTypes.H264, 640, 360) 18 | defer decoder.Close() 19 | encoder := ttLibGo.Encoders.Jpeg(320, 360, 90) 20 | defer encoder.Close() 21 | reader := ttLibGo.Readers.Flv() 22 | defer reader.Close() 23 | for { 24 | buffer := make([]byte, 65536) 25 | length, err := in.Read(buffer) 26 | if length == 0 { 27 | break 28 | } 29 | if err != nil { 30 | panic(err) 31 | } 32 | if !reader.ReadFrame( 33 | buffer, 34 | uint64(length), 35 | func(frame *ttLibGo.Frame) bool { 36 | switch frame.Type { 37 | case ttLibGo.FrameTypes.H264: 38 | decoder.DecodeFrame(frame, func(frame *ttLibGo.Frame) bool { 39 | // ここでyuvのデータをclipしてみる 40 | if frame.Type == ttLibGo.FrameTypes.Yuv420 { 41 | yuv420 := ttLibGo.Yuv420.Cast(frame) 42 | yuv420.Width = 320 43 | yuv420.YData = 160 44 | yuv420.UData = 80 45 | yuv420.VData = 80 46 | return encoder.EncodeFrame(yuv420, func(frame *ttLibGo.Frame) bool { 47 | // fmt.Println(frame) 48 | /* frame.GetBinaryBuffer(func(buf []byte) bool { 49 | file := fmt.Sprintf("out%d.jpeg", counter) 50 | out, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE, 0666) 51 | if err != nil { 52 | panic(err) 53 | } 54 | out.Write(buf) 55 | counter++ 56 | return true 57 | })*/ 58 | return true 59 | }) 60 | } 61 | return true 62 | }) 63 | // これを適当にdecodeしてみるか・・・ 64 | break 65 | default: 66 | break 67 | } 68 | return true 69 | }) { 70 | t.Errorf("読み込み失敗しました") 71 | return 72 | } 73 | if length < 65536 { 74 | break 75 | } 76 | } 77 | // t.Error() // とりあえずエラー完了にしとく 78 | } 79 | -------------------------------------------------------------------------------- /ttLibC.cpp: -------------------------------------------------------------------------------- 1 | #define TT_ATTRIBUTE_API __attribute__ ((visibility("hidden"))) 2 | #define TT_ATTRIBUTE_INNER __attribute__ ((visibility("hidden"))) 3 | 4 | #include "cppsrc/decoder/avcodec.cpp" 5 | #include "cppsrc/decoder/jpeg.cpp" 6 | #include "cppsrc/decoder/openh264.cpp" 7 | #include "cppsrc/decoder/opus.cpp" 8 | #include "cppsrc/decoder/png.cpp" 9 | #include "cppsrc/decoder/speex.cpp" 10 | #include "cppsrc/decoder/theora.cpp" 11 | #include "cppsrc/decoder/vorbis.cpp" 12 | #include "cppsrc/decoder.cpp" 13 | #include "cppsrc/encoder/fdkaac.cpp" 14 | #include "cppsrc/encoder/jpeg.cpp" 15 | #include "cppsrc/encoder/openh264.cpp" 16 | #include "cppsrc/encoder/opus.cpp" 17 | #include "cppsrc/encoder/speex.cpp" 18 | #include "cppsrc/encoder/theora.cpp" 19 | #include "cppsrc/encoder/vorbis.cpp" 20 | #include "cppsrc/encoder/x264.cpp" 21 | #include "cppsrc/encoder/x265.cpp" 22 | #include "cppsrc/encoder.cpp" 23 | #include "cppsrc/resampler/audio.cpp" 24 | #include "cppsrc/resampler/image.cpp" 25 | #include "cppsrc/resampler/libyuv.cpp" 26 | #include "cppsrc/resampler/resize.cpp" 27 | #include "cppsrc/resampler/soundtouch.cpp" 28 | #include "cppsrc/resampler/speexdsp.cpp" 29 | #include "cppsrc/resampler/swresample.cpp" 30 | #include "cppsrc/resampler/swscale.cpp" 31 | #include "cppsrc/resampler.cpp" 32 | #include "cppsrc/frame.cpp" 33 | #include "cppsrc/reader.cpp" 34 | #include "cppsrc/writer.cpp" 35 | #include "cppsrc/util.cpp" 36 | -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | extern void *StdMap_make(); 7 | extern void StdMap_putString(void *mp, const char *key, const char *value); 8 | extern void StdMap_putUint32(void *mp, const char *key, uint32_t value); 9 | extern void StdMap_putUint64(void *mp, const char *key, uint64_t value); 10 | extern void StdMap_putStringList(void *ptr, const char *key, const char *value); 11 | extern void StdMap_close(void *mp); 12 | */ 13 | import "C" 14 | import ( 15 | "fmt" 16 | "reflect" 17 | "unsafe" 18 | ) 19 | 20 | var mapUtil = struct { 21 | fromMap func(data map[string]interface{}) unsafe.Pointer 22 | close func(ptr unsafe.Pointer) 23 | }{ 24 | fromMap: func(data map[string]interface{}) unsafe.Pointer { 25 | stdMap := C.StdMap_make() 26 | for key, value := range data { 27 | ckey := C.CString(key) 28 | defer C.free(unsafe.Pointer(ckey)) 29 | switch reflect.TypeOf(value).Kind() { 30 | case reflect.String: 31 | cvalue := C.CString(value.(string)) 32 | defer C.free(unsafe.Pointer(cvalue)) 33 | C.StdMap_putString(stdMap, ckey, cvalue) 34 | case reflect.Uint32: 35 | C.StdMap_putUint32(stdMap, ckey, C.uint32_t(value.(uint32))) 36 | case reflect.Uint64: 37 | C.StdMap_putUint64(stdMap, ckey, C.uint64_t(value.(uint64))) 38 | case reflect.Slice: 39 | for _, v := range value.([]string) { 40 | cval := C.CString(v) 41 | defer C.free(unsafe.Pointer(cval)) 42 | C.StdMap_putStringList(stdMap, ckey, cval) 43 | } 44 | default: 45 | fmt.Println("unknown:") 46 | fmt.Println(value) 47 | fmt.Println(reflect.TypeOf(value).Kind()) 48 | } 49 | } 50 | return stdMap 51 | }, 52 | close: func(ptr unsafe.Pointer) { 53 | C.StdMap_close(ptr) 54 | }, 55 | } 56 | -------------------------------------------------------------------------------- /writer.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern void *ContainerWriter_make(void *mp); 10 | extern bool ContainerWriter_writeFrame(void *writer, void *frame, void *goFrame, uint32_t mode, uint32_t unitDuration, uintptr_t ptr); 11 | extern void ContainerWriter_close(void *writer); 12 | extern uint64_t ContainerWriter_getPts(void *writer); 13 | extern uint32_t ContainerWriter_getTimebase(void *writer); 14 | */ 15 | import "C" 16 | import ( 17 | "unsafe" 18 | ) 19 | 20 | type cttlibCWriter unsafe.Pointer 21 | 22 | // writerType writerタイプ 23 | type writerType struct{ value string } 24 | 25 | // IWriter メディアデータの書き出し 26 | type IWriter interface { 27 | WriteFrame( 28 | frame IFrame, 29 | callback func(data []byte) bool) bool 30 | Close() 31 | } 32 | 33 | // writer メディアデータ書き出し 34 | type writer struct { 35 | Type writerType 36 | Pts uint64 37 | Timebase uint32 38 | Mode uint32 39 | UnitDuration uint32 40 | cWriter cttlibCWriter 41 | call dataCall 42 | } 43 | 44 | // WriterModes Writerのモードリスト or で結合可能 45 | var WriterModes = struct { 46 | EnableDts uint32 47 | SplitAllKeyFrame uint32 48 | //SplitKeyFrame uint32 49 | SplitInnerFrame uint32 50 | SplitPFrame uint32 51 | SplitDisposableBFrame uint32 52 | SplitBFrame uint32 53 | }{ 54 | EnableDts: 0x20, 55 | SplitAllKeyFrame: 0x10, 56 | SplitInnerFrame: 0x01, 57 | SplitPFrame: 0x02, 58 | SplitDisposableBFrame: 0x04, 59 | SplitBFrame: 0x08, 60 | } 61 | 62 | // WriterTypes Writerタイプリスト 63 | var WriterTypes = struct { 64 | Flv writerType 65 | Mp4 writerType 66 | Mkv writerType 67 | Mpegts writerType 68 | Webm writerType 69 | }{ 70 | Flv: writerType{"flv"}, 71 | Mp4: writerType{"mp4"}, 72 | Mkv: writerType{"mkv"}, 73 | Mpegts: writerType{"mpegts"}, 74 | Webm: writerType{"webm"}, 75 | } 76 | 77 | func writerInit(writer *writer, params map[string]interface{}) *writer { 78 | v := mapUtil.fromMap(params) 79 | writer.cWriter = cttlibCWriter(C.ContainerWriter_make(v)) 80 | writer.Timebase = uint32(C.ContainerWriter_getTimebase(unsafe.Pointer(writer.cWriter))) 81 | mapUtil.close(v) 82 | return writer 83 | } 84 | 85 | // Writers Writers処理 86 | var Writers = struct { 87 | Flv func(videoType frameType, audioType frameType) *writer 88 | Mkv func(types ...frameType) *writer 89 | Webm func(types ...frameType) *writer 90 | Mp4 func(types ...frameType) *writer 91 | Mpegts func(types ...frameType) *mpegtsWriter 92 | }{ 93 | Flv: func(videoType frameType, audioType frameType) *writer { 94 | writer := writerInit(new(writer), map[string]interface{}{ 95 | "type": WriterTypes.Flv.value, 96 | "videoType": videoType.value, 97 | "audioType": audioType.value, 98 | }) 99 | writer.Type = WriterTypes.Flv 100 | writer.UnitDuration = 1000 101 | return writer 102 | }, 103 | Mkv: func(types ...frameType) *writer { 104 | var frameNames []string 105 | for _, v := range types { 106 | frameNames = append(frameNames, v.value) 107 | } 108 | writer := writerInit(new(writer), map[string]interface{}{ 109 | "type": WriterTypes.Mkv.value, 110 | "frameTypes": frameNames, 111 | }) 112 | writer.Type = WriterTypes.Mkv 113 | writer.UnitDuration = 1000 114 | return writer 115 | }, 116 | Webm: func(types ...frameType) *writer { 117 | var frameNames []string 118 | for _, v := range types { 119 | frameNames = append(frameNames, v.value) 120 | } 121 | writer := writerInit(new(writer), map[string]interface{}{ 122 | "type": WriterTypes.Webm.value, 123 | "frameTypes": frameNames, 124 | }) 125 | writer.Type = WriterTypes.Webm 126 | writer.UnitDuration = 1000 127 | return writer 128 | }, 129 | Mp4: func(types ...frameType) *writer { 130 | var frameNames []string 131 | for _, v := range types { 132 | frameNames = append(frameNames, v.value) 133 | } 134 | writer := writerInit(new(writer), map[string]interface{}{ 135 | "type": WriterTypes.Mp4.value, 136 | "frameTypes": frameNames, 137 | }) 138 | writer.Type = WriterTypes.Mp4 139 | writer.UnitDuration = 1000 140 | return writer 141 | }, 142 | Mpegts: func(types ...frameType) *mpegtsWriter { 143 | var frameNames []string 144 | for _, v := range types { 145 | frameNames = append(frameNames, v.value) 146 | } 147 | writer := writerInit((*writer)(new(mpegtsWriter)), map[string]interface{}{ 148 | "type": WriterTypes.Mpegts.value, 149 | "frameTypes": frameNames, 150 | }) 151 | writer.Type = WriterTypes.Mpegts 152 | writer.UnitDuration = 180000 153 | return (*mpegtsWriter)(writer) 154 | }, 155 | } 156 | 157 | func writerWriteFrame( 158 | writer *writer, 159 | frame IFrame, 160 | callback func(data []byte) bool) bool { 161 | if writer.cWriter == nil { 162 | return false 163 | } 164 | if frame == nil { 165 | return true 166 | } 167 | cframe := frame.newGoRefFrame() 168 | writer.call.callback = func(data []byte) bool { 169 | writer.Pts = uint64(C.ContainerWriter_getPts(unsafe.Pointer(writer.cWriter))) 170 | writer.Timebase = uint32(C.ContainerWriter_getTimebase(unsafe.Pointer(writer.cWriter))) 171 | return callback(data) 172 | } 173 | result := C.ContainerWriter_writeFrame( 174 | unsafe.Pointer(writer.cWriter), 175 | unsafe.Pointer(frame.refCFrame()), 176 | cframe, 177 | C.uint32_t(writer.Mode), 178 | C.uint32_t(writer.UnitDuration), 179 | C.uintptr_t(uintptr(unsafe.Pointer(&writer.call)))) 180 | frame.deleteGoRefFrame(cframe) 181 | return bool(result) 182 | } 183 | 184 | func writerClose(writer *writer) { 185 | C.ContainerWriter_close(unsafe.Pointer(writer.cWriter)) 186 | } 187 | 188 | // WriteFrame Frame書き出し 189 | func (writer *writer) WriteFrame( 190 | frame IFrame, 191 | callback func(data []byte) bool) bool { 192 | return writerWriteFrame(writer, frame, callback) 193 | } 194 | 195 | // Close 閉じる 196 | func (writer *writer) Close() { 197 | writerClose(writer) 198 | } 199 | -------------------------------------------------------------------------------- /writerMpegts.go: -------------------------------------------------------------------------------- 1 | package ttLibGo 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern bool ContainerWriter_writeInfo(void *writer, uintptr_t ptr); 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | type mpegtsWriter writer 15 | 16 | // WriteFrame Frame書き出し 17 | func (mpegtsWriter *mpegtsWriter) WriteFrame( 18 | frame IFrame, 19 | callback func(data []byte) bool) bool { 20 | return writerWriteFrame((*writer)(mpegtsWriter), frame, callback) 21 | } 22 | 23 | // Close 閉じる 24 | func (mpegtsWriter *mpegtsWriter) Close() { 25 | writerClose((*writer)(mpegtsWriter)) 26 | } 27 | 28 | // WriteInfo 情報タグ書き出し 29 | func (mpegtsWriter *mpegtsWriter) WriteInfo( 30 | callback func(data []byte) bool) bool { 31 | if mpegtsWriter.cWriter == nil { 32 | return false 33 | } 34 | mpegtsWriter.call.callback = callback 35 | result := C.ContainerWriter_writeInfo( 36 | unsafe.Pointer(mpegtsWriter.cWriter), 37 | C.uintptr_t(uintptr(unsafe.Pointer(&mpegtsWriter.call)))) 38 | return bool(result) 39 | } 40 | --------------------------------------------------------------------------------