← index
acidcamGL/source/ffmpeg_write.cpp
Source: acidcamGL/source/ffmpeg_write.cpp
#include "ffmpeg_write.h"

#ifdef __APPLE__
#include<mach-o/dyld.h>
#include<libgen.h>
#include<limits.h>
#include<stdint.h>
#endif


#include<sstream>
#include<fstream>
#ifndef _WIN32
#include<unistd.h>
#endif
// ffmpeg -y -s 640x480  -pixel_format bgr24 -f rawvideo -r 30 -i pipe: -vcodec libx265 -pix_fmt yuv420p -crf 24 test.mp4
#include"ipc_client.hpp"
#ifdef __APPLE__
std::string ffmpeg_path = "ffmpeg";
#else
std::string ffmpeg_path = "ffmpeg";
#endif
extern void sendString(const std::string &s);

char buffer[1024*1024];
std::fstream file;
int stdout_save;

FILE *open_ffmpeg(const char *output, const char *codec, const char *res, const char *dst_res, const char *fps, const char *crf) {
    

    #ifdef __APPLE__

    char exePath[PATH_MAX];
    uint32_t size = sizeof(exePath);
    if (_NSGetExecutablePath(exePath, &size) != 0)
        ffmpeg_path="ffmpeg";

    // Get directory
    std::string dir = dirname(exePath);
    ffmpeg_path = dir + "/ffmpeg";;

    #endif

    std::string tag;
    std::string preset_opts;
    std::string codec_str(codec);
    
    if(codec_str=="libx265")
        tag = "-tag:v hvc1";
    
    if(codec_str=="h264_nvenc") {
        preset_opts = "-preset fast -rc vbr -cq ";
        preset_opts += crf;
    } else if(codec_str=="hevc_nvenc") {
        preset_opts = "-preset fast -rc vbr -cq ";
        preset_opts += crf;
        tag = "-tag:v hvc1";
    } else if(codec_str=="av1_nvenc") {
        preset_opts = "-preset fast -rc vbr -cq ";
        preset_opts += crf;
    } else if(codec_str=="h264_videotoolbox") {
        preset_opts = "-q:v ";
        preset_opts += crf;
    } else if(codec_str=="hevc_videotoolbox") {
        preset_opts = "-q:v ";
        preset_opts += crf;
        tag = "-tag:v hvc1";
    } else if(codec_str=="h264_qsv") {
        preset_opts = "-q ";
        preset_opts += crf;
    } else if(codec_str=="hevc_qsv") {
        preset_opts = "-q ";
        preset_opts += crf;
        tag = "-tag:v hvc1";
    } else if(codec_str=="av1_qsv") {
        preset_opts = "-q ";
        preset_opts += crf;
    } else if(codec_str=="h264_amf") {
        preset_opts = "-qp_p ";
        preset_opts += crf;
    } else if(codec_str=="hevc_amf") {
        preset_opts = "-qp_p ";
        preset_opts += crf;
        tag = "-tag:v hvc1";
    } else if(codec_str=="h264_cuda" || codec_str=="hevc_cuda") {
        preset_opts = "-cq ";
        preset_opts += crf;
        if(codec_str=="hevc_cuda") tag = "-tag:v hvc1";
    } else if(codec_str=="h264_dxva2" || codec_str=="hevc_d3d11va") {
        preset_opts = "-crf ";
        preset_opts += crf;
        if(codec_str=="hevc_d3d11va") tag = "-tag:v hvc1";
    } else {
        preset_opts = "-crf ";
        preset_opts += crf;
    }
    
    std::ostringstream stream;
    stream << ffmpeg_path << " -y -s " << dst_res << " -pixel_format bgr24 -f rawvideo -r " << fps << " -i pipe: -vcodec " << codec << " -pix_fmt yuv420p " << preset_opts << " " << tag << " " << output;
    
    std::cout<<"acidcam: " << stream.str() << "\n";
    
#ifndef _WIN32
    FILE *fptr = popen(stream.str().c_str(), "w");
#else
    FILE *fptr = _popen(stream.str().c_str(), "wb");
#endif
    if(!fptr) {
        std::cerr << "Error: could not open ffmpeg\n";
        return 0;
    }
    return fptr;
}

//ffmpeg -f avfoundation -i ":iShowU Audio Capture" -acodec libmp3lame -ab 128k -f mp3 -

void list_devices() {
#ifdef __APPLE__
    std::string s = ffmpeg_path + " -list_devices true -f avfoundation -i dummy";
    FILE *fptr = popen(s.c_str(), "r");
    if(!fptr) {
        std::cout << "acidcam: Error: could not read file...\n";
        exit(0);
    }
    while(!feof(fptr)) {
        char buf[1024];
        fgets(buf, 1024, fptr);
        std::cout << buf;
    }
    pclose(fptr);
#endif
}

void write_ffmpeg(FILE *fptr, cv::Mat &frame) {
    fwrite(frame.ptr(), sizeof(char), frame.total()*frame.elemSize(), fptr);
}

void close_stdout() {
    
}

void mux_audio(const char *output, const char *src, const char *final_file) {
    std::ostringstream stream;
    stream << ffmpeg_path << " -y -i \"" << output << "\" -i \"" << src << "\" -c copy -map 0:v:0 -map 1:a:0? -shortest \"" << final_file << "\"";
    std::cout << "acidcam: " << stream.str() << "\n";
#ifndef _WIN32
    FILE *fptr = popen(stream.str().c_str(), "r");
#else
    FILE *fptr = _popen(stream.str().c_str(), "r");
#endif
    if(!fptr) {
        std::cerr << "Error: could not open ffmpeg\n";
        return;
    }
#ifndef _WIN32
    pclose(fptr);
#else
    _pclose(fptr);
#endif
}

void rotate_90(const char *output, const char *src) {
    std::ostringstream stream;
    stream << ffmpeg_path << " -i \"" << output << "\" -c copy  -metadata:s:v:0 rotate=90 " << "\"" << src << "\"";
    std::cout << "acidcam: " << stream.str() << "\n";
#ifndef _WIN32
    FILE *fptr = popen(stream.str().c_str(), "r");
#else
    FILE *fptr = _popen(stream.str().c_str(), "r");
#endif
    if(!fptr) {
        std::cerr << "Error: could not open ffmpeg\n";
        return;
    }
#ifndef _WIN32
    pclose(fptr);
#else
    _pclose(fptr);
#endif
    
}