星期六, 6月 27, 2015

Video Streaming Server, MP4, moov, and pseudo streaming

MP4 預設格式不適合seek in tcp streaming, 把moov atom移到MP4檔頭前,就可以加強seek功能


Streaming a video file to an html5 video player with Node.js so that the video controls continue to work?
http://stackoverflow.com/questions/24976123/streaming-a-video-file-to-an-html5-video-player-with-node-js-so-that-the-video-c

Seeking videos beyond the buffer line
http://1stdev.com/tremendum-transcoder/articles/seeking-videos-beyond-the-buffer-line/

HTTP Streaming 相關技術 pseudo, live
http://virdust.blogspot.tw/2011/11/http-streaming-pseudo-live.html

星期二, 6月 23, 2015

星期日, 6月 21, 2015

Django Class Base View Examples

https://docs.djangoproject.com/en/1.8/ref/class-based-views/

Generic display views
Model Name as suffix name, e.g., author_xxx.html
DetailView
_detail.html
ListView
_list.html


Generic editing views

FormView

CreateView
_form.html
UpdateView
_form.html
DeleteView
_confirm_delete.html









Reference:

好投影片
Django class-based views: survival guide for novices
http://www.slideshare.net/giordanileonardo/django-cb-vssurvivalguidefornovicesv2

Best Practices for Class-Based Views
http://www.slideshare.net/starwilly/two-scoopsofdjangocbv


好範例,很小很容易理解

Django 1.8 Tutorial - 1. A Minimal Application Made Using Generic Class Based Views
http://riceball.com/d/content/django-18-minimal-application-using-generic-class-based-views

Notes:
練習中少了一些命令
settings.py -->'comment'
python manage.py makemigration
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

Pycharm note:
把專案根目錄Make Directory as sources root 可以避免urls.py找不到相對import 檔提示問題
https://www.jetbrains.com/pycharm/help/configuring-folders-within-a-content-root.html


Getting started with Generic Class Based Views in Django
http://www.onespacemedia.com/news/2014/feb/5/getting-started-generic-class-based-views-django/

Django 中文習學資源


Django筆記
5 Stars, 描述很完整,技術細節說明很清楚的學習資源
http://dokelung-blog.logdown.com/posts/235592-django-notes-table-of-contents

星期六, 6月 06, 2015

Omnet++ INET UDPBasicApp生命週期觀察

Summary:

1. UDPBasicApp::initialize(int stage)
2. if (stage == INITSTAGE_LOCAL) {
   selfMsg = new cMessage("sendTimer");

2.1 selfMsg變數表「排程狀態」,用來當事件參數 OperationalBase::handleMessage(cMessage *message),做狀態機,控制用。

3. stage ++
4. 直到stage=12, i.e,  isInitializeStage(stage)==true, 執行     handleNodeStart(nullptr);
5.  handleNodeStart,     排程
selfMsg->setKind(START);
        scheduleAt(start, selfMsg);

以上是戴入omnet.ini就會執行的code

6. 至於真正的封包排程, schedule要等到按run才會執行, 此時 if (isOperational)為真
7. 事件發生,執行handleMessage, 會再呼叫  handleMessageWhenUp(message);
8. 會再呼叫processStart(), 正式app的啟動,
     case START:
                processStart();
                break;
9. processStart()呼叫 processSend();
10.  processSend()依設定的sendInterval參數, 送出封包後,再排程下次傳送時間點 
11. 重覆7-11, 執行
            case SEND:
                processSend();


                break;


-----------------------------------------------------------------
Details:

omnet++載入時omnet.ini會執行

0. stage=0, i.e, INITSTAGE_LOCAL
1. 一開始初始化階段,執行程式碼
   ApplicationBase::initialize(stage);
  if (stage == INITSTAGE_LOCAL) {
  EV_INFO << "hsuth: INITSTAGE_LOCAL"<< endl;
程式碼,進行初始化。
}

2. 每次跑完stage++
3. 在stage=12時, isInitializeStage(stage)會傳回 true, 此時會跑 handleNodeStart(nullptr);

void OperationalBase::initialize(int stage)
{
    if (isInitializeStage(stage)) {
        NodeStatus *nodeStatus = dynamic_cast(findContainingNode(this)->getSubmodule("status"));
        setOperational(!nodeStatus || nodeStatus->getState() == NodeStatus::UP);
        if (isOperational) {
            EV_INFO << "hsuth: OperationalBase::handleNodeStart"<< endl;
            handleNodeStart(nullptr);
        }
    }
}
會呼叫
bool UDPBasicApp::handleNodeStart(IDoneCallback *doneCallback)
{
    EV_INFO << "hsuth: UDPBasicApp::handleNodeStart"<< endl;
    simtime_t start = std::max(startTime, simTime());
    if ((stopTime < SIMTIME_ZERO) || (start < stopTime) || (start == stopTime && startTime == stopTime)) {
        selfMsg->setKind(START);
        scheduleAt(start, selfMsg);
    }
    return true;
}


當按run時,才會跑排程
排程,時間到呼叫handleMessage, 在
void OperationalBase::handleMessage(cMessage *message)
{
    if (isOperational)
        handleMessageWhenUp(message);
    else
        handleMessageWhenDown(message);
}
會呼叫 UDPBasicApp::handleMessageWhenUp

接著會跑到
void UDPBasicApp::handleMessageWhenUp(cMessage *msg)
{
    if (msg->isSelfMessage()) {
        ASSERT(msg == selfMsg);
        switch (selfMsg->getKind()) {
            case START:
                processStart();
                break;

執行
void UDPBasicApp::processStart()
{

if (!destAddresses.empty()) {
        selfMsg->setKind(SEND);
        processSend();
    }

}

執行

void UDPBasicApp::processSend()
{
    sendPacket();
    simtime_t d = simTime() + par("sendInterval").doubleValue();
    if (stopTime < SIMTIME_ZERO || d < stopTime) {
        selfMsg->setKind(SEND);
        scheduleAt(d, selfMsg);
    }
    else {
        selfMsg->setKind(STOP);
        scheduleAt(stopTime, selfMsg);
    }

}

重覆


void UDPBasicApp::handleMessageWhenUp(cMessage *msg)
{
    if (msg->isSelfMessage()) {
        ASSERT(msg == selfMsg);
        switch (selfMsg->getKind()) {
            case START:
                processStart();
                break;

            case SEND:
                processSend();
                break;

取得sendInterval,一直重覆,直到simulation end

void UDPBasicApp::processSend()
{
    sendPacket();
    simtime_t d = simTime() + par("sendInterval").doubleValue();
    if (stopTime < SIMTIME_ZERO || d < stopTime) {
        selfMsg->setKind(SEND);
        scheduleAt(d, selfMsg);
    }
    else {
        selfMsg->setKind(STOP);
        scheduleAt(stopTime, selfMsg);
    }
}