
/*---------------------------------------------------------------------------*/
/* video_transcoder.cpp                                                      */
/* copyright (c) innovaphone 2015                                            */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#include "platform/platform.h"

#include "platform/phone_linux.h"
#include "common/os/iomux.h"
#include "common/interface/socket.h"
#include "common/ilib/str.h"
#include "common/interface/media.h"
#include "common/interface/task.h"
#include "common/interface/stask.h"
#include "common/lib/tasks_file.h"
#include "client/logflags/debug_logflags.h"
#include "client/config/debug_readlog.h"
#include "client/linux/client_main/appclient_main.h"

#include "video_transcoder.h"

extern class UAppClientMain * appClientMainUser;

#define MAX_TRANSCODERS   8
static class VideoTranscoder *(videoTranscoderMap[MAX_TRANSCODERS]) = { NULL };

/*---------------------------------------------------------------------------*/

class VideoTranscoderClose {};

class VideoTranscoder : public IMediaTranscoder,
    public UIoExecSubclass<VideoTranscoderClose>
{
    void SetExec(IIoMux * iomux, UIoExecSubclass<VideoTranscoderClose> * ioContext, VideoTranscoderClose * execContext) { iomux->SetExec(ioContext, execContext); };
    void IoExec(VideoTranscoderClose * context);

    void Close();
    void Transcode(const void * buf, int len, dword timestamp, dword duration, short sequenceDiff, int width, int height, int stride, dword flags);

public:
    VideoTranscoder(class IIoMux * const iomux, class UMediaTranscoder * const user, class IInstanceLog * log, enum VideoCoder from, enum VideoCoder to);
    ~VideoTranscoder();

    class IIoMux * iomux;
    UMediaTranscoder * user;
    enum VideoCoder from;
    enum VideoCoder to;
    int transcoder_id;
};

class IMediaTranscoder * IMediaTranscoder::Create(class IIoMux * const iomux, class UMediaTranscoder * const user, class IInstanceLog * log, enum VideoCoder from, enum VideoCoder to)
{
    return new VideoTranscoder(iomux, user, log, from, to);
}

void VideoTranscoder::IoExec(VideoTranscoderClose * context)
{
    user->MediaTranscoderCloseResult(this);
}

VideoTranscoder::VideoTranscoder(class IIoMux * const iomux, class UMediaTranscoder * const user, class IInstanceLog * log, enum VideoCoder from, enum VideoCoder to)
{
    this->iomux = iomux;
    this->user = user;
    this->from = from;
    this->to = to;
    transcoder_id = -1;
}

VideoTranscoder::~VideoTranscoder()
{
}

void VideoTranscoder::Close()
{
    if (transcoder_id != -1) {
        appClientMainUser->AppClientMainVideoTranscode(transcoder_id, 0, 0, 0, NULL, 0, 0, 0, 0, 0,
            (from == VideoCoder::H264) ? FORMS_WEBCAM_CODER_H264 : ((from == VideoCoder::VP8) ? FORMS_WEBCAM_CODER_VP8 : FORMS_WEBCAM_CODER_IYUV),
            (to == VideoCoder::H264) ? FORMS_WEBCAM_CODER_H264 : ((to == VideoCoder::VP8) ? FORMS_WEBCAM_CODER_VP8 : FORMS_WEBCAM_CODER_IYUV));
    }
    else {
        SetExec(iomux, this, (VideoTranscoderClose *)0);
    }
}

void VideoTranscoder::Transcode(const void * buf, int len, dword timestamp, dword duration, short sequenceDiff, int width, int height, int stride, dword flags)
{
    if (transcoder_id == -1) {
        do {
            transcoder_id++;
        }
        while((transcoder_id < MAX_TRANSCODERS) && videoTranscoderMap[transcoder_id]);
        if (transcoder_id == MAX_TRANSCODERS) {
            debug->printf("VideoTranscoder::Transcode out of transcoders");
            return;
        }
        videoTranscoderMap[transcoder_id] = this;
    }
    appClientMainUser->AppClientMainVideoTranscode(transcoder_id, timestamp, duration, sequenceDiff, buf, len, width, height, stride, flags,
        (from == VideoCoder::H264) ? FORMS_WEBCAM_CODER_H264 : ((from == VideoCoder::VP8) ? FORMS_WEBCAM_CODER_VP8 : FORMS_WEBCAM_CODER_IYUV),
        (to == VideoCoder::H264) ? FORMS_WEBCAM_CODER_H264 : ((to == VideoCoder::VP8) ? FORMS_WEBCAM_CODER_VP8 : FORMS_WEBCAM_CODER_IYUV));
}

void phone_video_transcode(int id, dword timestamp, dword duration, short sequenceDiff, int length, const byte *data, int width, int height, int stride, dword flags)
{
    VideoTranscoder * transcoder = videoTranscoderMap[id];
    if (!transcoder) return;
    if (data) {
        transcoder->user->TranscodeResult(transcoder, data, length, timestamp, duration, sequenceDiff, width, height, stride, flags);
    }
    else {
        videoTranscoderMap[id] = NULL;
        transcoder->transcoder_id = -1;
        transcoder->user->MediaTranscoderCloseResult(transcoder);
    }
}

/*---------------------------------------------------------------------------*/
