-
-
Save roxlu/62e8a92beff6845eed92 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Webm.h" | |
void webm_vpx_write_cb(const vpx_codec_cx_pkt_t* pkt, void* user) { | |
printf("Got encoded frame!\n"); | |
} | |
void webm_encoder_thread(void* user) { | |
Webm& webm = *(static_cast<Webm*>(user)); | |
std::vector<WebmPacket*> work_packets; | |
WebmPacket* pkt = NULL; | |
bool stop = false; | |
while(true) { | |
uv_mutex_lock(&webm.packets_mutex); | |
std::copy(webm.packets.begin(), webm.packets.end(), std::back_inserter(work_packets)); | |
webm.packets.clear(); | |
uv_mutex_unlock(&webm.packets_mutex); | |
for(std::vector<WebmPacket*>::iterator it = work_packets.begin(); it != work_packets.end(); ++it) { | |
pkt = *it; | |
webm.vid_enc.encode(pkt->buf, pkt->timestamp); | |
delete[] pkt->buf; | |
delete pkt; | |
// pkt = NULL; | |
} | |
work_packets.clear(); | |
printf("??\n"); | |
uv_mutex_lock(&webm.stop_mutex); | |
stop = webm.must_stop; | |
uv_mutex_unlock(&webm.stop_mutex); | |
if(stop) { | |
printf("STOPPPING.\n"); | |
break; | |
} | |
} | |
} | |
Webm::Webm() | |
:ebml(NULL) | |
,vid_in_w(0) | |
,vid_in_h(0) | |
,vid_out_w(0) | |
,vid_out_h(0) | |
,vid_fps(0) | |
,vid_fmt(VPX_IMG_FMT_NONE) | |
,vid_num_frames(0) | |
,must_stop(false) | |
{ | |
} | |
Webm::~Webm() { | |
shutdown(); | |
} | |
bool Webm::setupVideo(int inW, | |
int inH, | |
int outW, | |
int outH, | |
int fps, | |
vpx_img_fmt fmt) | |
{ | |
vid_in_w = inW; | |
vid_in_h = inH; | |
vid_out_w = outW; | |
vid_out_h = outH; | |
vid_fps = fps; | |
vid_fmt = fmt; | |
bool is_setup = vid_enc.setup(vid_in_w, vid_in_h, vid_out_w, | |
vid_out_h, vid_fps, vid_fmt, | |
webm_vpx_write_cb, this); | |
if(!is_setup) { | |
return false; | |
} | |
return true; | |
} | |
bool Webm::setupAudio() { | |
return true; | |
} | |
bool Webm::initialize() { | |
if(!initializeThread()) { | |
return false; | |
} | |
if(!vid_enc.initialize()) { | |
return false; | |
} | |
return true; | |
} | |
bool Webm::open() { | |
if(!openEBML()) { | |
return false; | |
} | |
return true; | |
} | |
bool Webm::openEBML() { | |
assert(ebml != NULL); | |
EBMLHeader h; | |
h.ebml_version = 1; | |
h.ebml_read_version = 1; | |
h.ebml_max_id_length = 4; | |
h.ebml_max_size_length = 8; | |
h.doctype = "webm"; | |
h.doctype_version = 2; | |
h.doctype_read_version = 2; | |
return ebml->open(h); | |
} | |
bool Webm::shutdown() { | |
stopThread(); | |
return true; | |
} | |
bool Webm::close() { | |
ebml->close(); | |
vid_num_frames = 0; | |
return true; | |
} | |
bool Webm::startThread() { | |
uv_thread_create(&thread, webm_encoder_thread, this); | |
return true; | |
} | |
bool Webm::stopThread() { | |
uv_mutex_lock(&stop_mutex); | |
must_stop = true; | |
uv_mutex_unlock(&stop_mutex); | |
uv_thread_join(&thread); | |
return true; | |
} | |
bool Webm::initializeThread() { | |
if(uv_mutex_init(&stop_mutex) != 0) { | |
return false; | |
} | |
if(uv_mutex_init(&packets_mutex) != 0) { | |
return false; | |
} | |
return true; | |
} | |
void Webm::addVideoFrame(unsigned char* data, int nbytes) { | |
WebmPacket* p = new WebmPacket(); | |
if(!p) { | |
printf("ERROR: out of mem\n"); | |
return; | |
} | |
p->buf = new unsigned char[nbytes]; | |
if(!p->buf) { | |
printf("ERROR: out of mem\n"); | |
return; | |
} | |
memcpy(p->buf, data, nbytes); | |
p->timestamp = vid_num_frames; | |
p->type = WPT_VIDEO; | |
uv_mutex_lock(&packets_mutex); | |
packets.push_back(p); | |
uv_mutex_unlock(&packets_mutex); | |
vid_num_frames++; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef ROXLU_WEBM_H | |
#define ROXLU_WEBM_H | |
#include <assert.h> | |
#include <inttypes.h> | |
#include <vector> | |
#include <algorithm> | |
extern "C" { | |
# include <uv.h> | |
} | |
#include "EBML.h" | |
#include "VPX.h" | |
enum WebmPacketTypes { | |
WPT_VIDEO, | |
WPT_AUDIO | |
}; | |
struct WebmPacket { | |
unsigned char* buf; | |
int nbytes; | |
char type; | |
int64_t timestamp; | |
}; | |
void webm_vpx_write_cb(const vpx_codec_cx_pkt_t* pkt, void* user); | |
void webm_encoder_thread(void* user); | |
class Webm { | |
public: | |
Webm(); | |
~Webm(); | |
void setEBML(EBML* ebml); | |
bool setupVideo(int inW, /* video in width */ | |
int inH, /* video in height */ | |
int outW, /* video out width */ | |
int outH, /* video out height */ | |
int fps, /* video fps */ | |
vpx_img_fmt fmt); /* video pixel format */ | |
bool setupAudio(); // todo | |
bool initialize(); | |
bool shutdown(); | |
bool open(); | |
bool close(); | |
bool startThread(); | |
bool stopThread(); | |
void addVideoFrame(unsigned char* data, int nbytes); | |
private: | |
bool openEBML(); /* open the EBML stream */ | |
bool initializeThread(); /* initialize thread related members */ | |
public: | |
EBML* ebml; | |
/* video */ | |
int vid_in_w; /* video input width */ | |
int vid_in_h; /* video input height */ | |
int vid_out_w; /* video output width */ | |
int vid_out_h; /* video output height */ | |
int vid_fps; /* video frames per second */ | |
int64_t vid_num_frames; /* number of encoded/added frames */ | |
vpx_img_fmt vid_fmt; /* video input pixel format */ | |
VPX vid_enc; /* video encoder; wrapper around libvpx */ | |
std::vector<WebmPacket*> packets; /* contains video/audio packets that needs to be encoded */ | |
public: | |
/* threading */ | |
bool must_stop; | |
uv_thread_t thread; | |
uv_mutex_t stop_mutex; | |
uv_mutex_t packets_mutex; | |
}; | |
inline void Webm::setEBML(EBML* ebml) { | |
this->ebml = ebml; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment