diff --git a/README.md b/README.md
index b68b1dbdb..3970859a0 100755
--- a/README.md
+++ b/README.md
@@ -117,7 +117,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw
* nginx v1.5.0: 139524 lines
### History
-* v0.7, 2013-11-30, add transcoding params to config.
+* v0.7, 2013-11-30, support live stream transcoding by ffmpeg.
* v0.7, 2013-11-30, support --with/without -ffmpeg, build ffmpeg-2.1.
* v0.7, 2013-11-30, add ffmpeg-2.1, x264-core138, lame-3.99.5, libaacplus-2.0.2.
* v0.6, 2013-11-29, v0.6 released. 16094 lines.
diff --git a/trunk/src/core/srs_core_config.cpp b/trunk/src/core/srs_core_config.cpp
index 8ccd54e3c..055aac146 100644
--- a/trunk/src/core/srs_core_config.cpp
+++ b/trunk/src/core/srs_core_config.cpp
@@ -568,7 +568,7 @@ SrsConfDirective* SrsConfig::get_vhost_enabled(std::string vhost)
return conf->get("enabled");
}
-SrsConfDirective* SrsConfig::get_transcode(std::string vhost)
+SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope)
{
SrsConfDirective* conf = get_vhost(vhost);
@@ -576,7 +576,16 @@ SrsConfDirective* SrsConfig::get_transcode(std::string vhost)
return NULL;
}
- return conf->get("transcode");
+ SrsConfDirective* transcode = conf->get("transcode");
+ if (!transcode) {
+ return NULL;
+ }
+
+ if (transcode->arg0() == scope) {
+ return transcode;
+ }
+
+ return NULL;
}
SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost)
diff --git a/trunk/src/core/srs_core_config.hpp b/trunk/src/core/srs_core_config.hpp
index 984e12742..ba62618d7 100644
--- a/trunk/src/core/srs_core_config.hpp
+++ b/trunk/src/core/srs_core_config.hpp
@@ -114,7 +114,7 @@ public:
virtual int parse_options(int argc, char** argv);
virtual SrsConfDirective* get_vhost(std::string vhost);
virtual SrsConfDirective* get_vhost_enabled(std::string vhost);
- virtual SrsConfDirective* get_transcode(std::string vhost);
+ virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope);
virtual SrsConfDirective* get_gop_cache(std::string vhost);
virtual SrsConfDirective* get_forward(std::string vhost);
virtual SrsConfDirective* get_hls(std::string vhost);
diff --git a/trunk/src/core/srs_core_encoder.cpp b/trunk/src/core/srs_core_encoder.cpp
index f31ceb99e..577b58f2a 100644
--- a/trunk/src/core/srs_core_encoder.cpp
+++ b/trunk/src/core/srs_core_encoder.cpp
@@ -25,22 +25,89 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include
#include
+#include
+
+#define SRS_ENCODER_SLEEP_MS 2000
SrsEncoder::SrsEncoder()
{
+ tid = NULL;
+ loop = false;
}
SrsEncoder::~SrsEncoder()
{
+ on_unpublish();
}
-int SrsEncoder::on_publish(std::string vhost, std::string app, std::string stream)
+int SrsEncoder::on_publish(std::string _vhost, std::string _app, std::string _stream)
{
int ret = ERROR_SUCCESS;
+
+ vhost = _vhost;
+ app = _app;
+ stream = _stream;
+
+ srs_assert(!tid);
+ if((tid = st_thread_create(encoder_thread, this, 1, 0)) == NULL){
+ ret = ERROR_ST_CREATE_FORWARD_THREAD;
+ srs_error("st_thread_create failed. ret=%d", ret);
+ return ret;
+ }
+
return ret;
}
void SrsEncoder::on_unpublish()
{
+ if (tid) {
+ loop = false;
+ st_thread_interrupt(tid);
+ st_thread_join(tid, NULL);
+ tid = NULL;
+ }
+}
+
+int SrsEncoder::cycle()
+{
+ int ret = ERROR_SUCCESS;
+ return ret;
+}
+
+void SrsEncoder::encoder_cycle()
+{
+ int ret = ERROR_SUCCESS;
+
+ log_context->generate_id();
+ srs_trace("encoder cycle start");
+
+ while (loop) {
+ if ((ret = cycle()) != ERROR_SUCCESS) {
+ srs_warn("encoder cycle failed, ignored and retry, ret=%d", ret);
+ } else {
+ srs_info("encoder cycle success, retry");
+ }
+
+ if (!loop) {
+ break;
+ }
+
+ st_usleep(SRS_ENCODER_SLEEP_MS * 1000);
+ }
+
+ // TODO: kill ffmpeg when finished and it alive
+
+ srs_trace("encoder cycle finished");
+}
+
+void* SrsEncoder::encoder_thread(void* arg)
+{
+ SrsEncoder* obj = (SrsEncoder*)arg;
+ srs_assert(obj != NULL);
+
+ obj->loop = true;
+ obj->encoder_cycle();
+
+ return NULL;
}
diff --git a/trunk/src/core/srs_core_encoder.hpp b/trunk/src/core/srs_core_encoder.hpp
index 3ea39ee08..d4932d442 100644
--- a/trunk/src/core/srs_core_encoder.hpp
+++ b/trunk/src/core/srs_core_encoder.hpp
@@ -31,14 +31,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include
+#include
+
class SrsEncoder
{
+private:
+ std::string vhost;
+ std::string app;
+ std::string stream;
+private:
+ st_thread_t tid;
+ bool loop;
public:
SrsEncoder();
virtual ~SrsEncoder();
public:
virtual int on_publish(std::string vhost, std::string app, std::string stream);
virtual void on_unpublish();
+private:
+ virtual int cycle();
+ virtual void encoder_cycle();
+ static void* encoder_thread(void* arg);
};
#endif
diff --git a/trunk/src/core/srs_core_forward.cpp b/trunk/src/core/srs_core_forward.cpp
index 26bdbec13..967ba807b 100644
--- a/trunk/src/core/srs_core_forward.cpp
+++ b/trunk/src/core/srs_core_forward.cpp
@@ -43,10 +43,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SrsForwarder::SrsForwarder()
{
client = NULL;
- tid = NULL;
stfd = NULL;
- loop = false;
stream_id = 0;
+
+ tid = NULL;
+ loop = false;
}
SrsForwarder::~SrsForwarder()
@@ -221,7 +222,7 @@ std::string SrsForwarder::parse_server(std::string host)
return ipv4;
}
-int SrsForwarder::forward_cycle_imp()
+int SrsForwarder::cycle()
{
int ret = ERROR_SUCCESS;
@@ -316,7 +317,7 @@ void SrsForwarder::forward_cycle()
srs_trace("forward cycle start");
while (loop) {
- if ((ret = forward_cycle_imp()) != ERROR_SUCCESS) {
+ if ((ret = cycle()) != ERROR_SUCCESS) {
srs_warn("forward cycle failed, ignored and retry, ret=%d", ret);
} else {
srs_info("forward cycle success, retry");
diff --git a/trunk/src/core/srs_core_forward.hpp b/trunk/src/core/srs_core_forward.hpp
index dde732810..3bb8d4639 100644
--- a/trunk/src/core/srs_core_forward.hpp
+++ b/trunk/src/core/srs_core_forward.hpp
@@ -71,7 +71,7 @@ private:
virtual int connect_server();
std::string parse_server(std::string host);
private:
- virtual int forward_cycle_imp();
+ virtual int cycle();
virtual int forward();
virtual void forward_cycle();
static void* forward_thread(void* arg);