This source file includes following definitions.
- Dektec_Blit
- Dektec_Flush
- Dektec_LockBackBuffer
- Dektec_Shutdown
- Dektec_ProcessEvent
- Dektec_resize
- Dektec_Setup
- NewDektecVideoOutput
- DeleteDektecVideoOutput
- QueryInterfaces
- LoadInterface
- ShutdownInterface
#define _DTAPI_DISABLE_AUTO_LINK
#include <DTAPI.h>
extern "C" {
#include <gpac/modules/video_out.h>
#include <gpac/modules/audio_out.h>
#include <gpac/constants.h>
#include <gpac/setup.h>
#ifdef NDEBUG
#define tru 1
#else
#define tru 0
#endif
#if 1
#define DWIDTH 1280
#define DHEIGHT 720
#define DFORMAT DTAPI_IOCONFIG_720P59_94
#define DNUMFIELDS 1
#else
#define DWIDTH 1920
#define DHEIGHT 1080
#define DFORMAT DTAPI_IOCONFIG_1080I50
#define DNUMFIELDS 2
#endif
typedef struct
{
char *pixels;
unsigned char *pixels_UYVY;
u32 width, height, pixel_format, bpp;
DtDevice *dvc;
DtFrameBuffer *dtf;
bool isSending;
s64 frameNum;
} DtContext;
void dx_copy_pixels(GF_VideoSurface *dst_s, const GF_VideoSurface *src_s, const GF_Window *src_wnd);
static GF_Err Dektec_Blit(GF_VideoOutput *dr, GF_VideoSurface *video_src, GF_Window *src_wnd, GF_Window *dst_wnd, u32 overlay_type)
{
DtContext *dtc = (DtContext*)dr->opaque;
GF_VideoSurface temp_surf;
memset(&temp_surf, 0, sizeof(GF_VideoSurface));
temp_surf.pixel_format = GF_PIXEL_UYVY;
temp_surf.video_buffer = (char*)dtc->pixels_UYVY;
temp_surf.pitch_y = dtc->width*2;
dx_copy_pixels(&temp_surf, video_src, src_wnd);
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Dektec Out] Blit\n"));
return GF_OK;
}
static GF_Err Dektec_Flush(GF_VideoOutput *dr, GF_Window *dest)
{
DtContext *dtc = (DtContext*)dr->opaque;
DtFrameBuffer *dtf = dtc->dtf;
DTAPI_RESULT res;
if (dest->w != DWIDTH || dest->h != DHEIGHT) {
GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Dektec Out] Discard data with wrong dimensions\n"));
if (tru) return GF_OK;
}
if (!dtc->isSending) {
res = dtf->Start();
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_WARNING, GF_LOG_MODULE, ("[Dektec Out] Can't start transmission: %s.\n", DtapiResult2Str(res)));
} else {
GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Dektec Out] Transmission started.\n"));
dtc->isSending = true;
}
}
s64 firstSafeFrame=-1, lastSafeFrame=-1;
res = dtf->WaitFrame(firstSafeFrame, lastSafeFrame);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't get the next frame: %s\n", DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
if (dtc->frameNum == -1)
dtc->frameNum = firstSafeFrame;
int numLines=-1, numWritten=DWIDTH*DHEIGHT*2/DNUMFIELDS;
res = dtf->WriteVideo(dtc->frameNum, dtc->pixels_UYVY, numWritten, DTAPI_SDI_FIELD1, DTAPI_SDI_8B, 1, numLines);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't write frame "LLD": %s\n", dtc->frameNum, DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
if (DNUMFIELDS > 1) {
assert(DNUMFIELDS == 2);
numLines=-1, numWritten=DWIDTH*DHEIGHT*2/DNUMFIELDS;
res = dtf->WriteVideo(dtc->frameNum, dtc->pixels_UYVY+numWritten, numWritten, DTAPI_SDI_FIELD2, DTAPI_SDI_8B, 1, numLines);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't write frame "LLD": %s\n", dtc->frameNum, DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
}
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Dektec Out] Written frame "LLD" [(0x%X,0x%X,0x%X,0x%X)(0x%X,0x%X,0x%X,0x%X)(0x%X,0x%X,0x%X,0x%X)(0x%X,0x%X,0x%X,0x%X)]\n", dtc->frameNum, DWIDTH, DHEIGHT,
dtc->pixels_UYVY[0], dtc->pixels_UYVY[1], dtc->pixels_UYVY[2], dtc->pixels_UYVY[3], dtc->pixels_UYVY[4], dtc->pixels_UYVY[5], dtc->pixels_UYVY[6], dtc->pixels_UYVY[7],
dtc->pixels_UYVY[8], dtc->pixels_UYVY[9], dtc->pixels_UYVY[10], dtc->pixels_UYVY[11], dtc->pixels_UYVY[12], dtc->pixels_UYVY[13], dtc->pixels_UYVY[14], dtc->pixels_UYVY[15]));
res = dtf->AncCommit(dtc->frameNum);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't write VANC for frame "LLD": %s\n", dtc->frameNum, DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
dtc->frameNum++;
#ifdef DEKTEC_DUMP_UYVY
char szName[1024];
sprintf(szName, "test.uyvy");
FILE *f = fopen(szName, "ab");
fwrite(dtc->pixels_UYVY, dtc->width*dtc->height*2, 1, f);
fclose(f);
#endif
return GF_OK;
}
static GF_Err Dektec_LockBackBuffer(GF_VideoOutput *dr, GF_VideoSurface *vi, Bool do_lock)
{
DtContext *dtc = (DtContext*)dr->opaque;
if (do_lock) {
if (!vi) return GF_BAD_PARAM;
memset(vi, 0, sizeof(GF_VideoSurface));
vi->height = dtc->height;
vi->width = dtc->width;
vi->video_buffer = dtc->pixels;
vi->pitch_x = dtc->bpp;
vi->pitch_y = dtc->bpp * vi->width;
vi->pixel_format = GF_PIXEL_RGB_24;
}
return GF_OK;
}
static void Dektec_Shutdown(GF_VideoOutput *dr)
{
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Dektec Out] Dektec_Shutdown\n"));
DtContext *dtc = (DtContext*)dr->opaque;
DtFrameBuffer *dtf = dtc->dtf;
DTAPI_RESULT res = dtf->Start(false);
if (tru && res != DTAPI_OK)
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't stop transmission: %s\n", DtapiResult2Str(res)));
dtf->Detach();
dtc->dvc->Detach();
dtc->isSending = false;
}
static GF_Err Dektec_ProcessEvent(GF_VideoOutput *dr, GF_Event *evt)
{
DtFrameBuffer *dtf = (DtFrameBuffer*)(((DtContext*)dr->opaque)->dtf);
if (evt) {
switch (evt->type) {
case GF_EVENT_VIDEO_SETUP:
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Dektec Out] resize (%ux%u) received.\n", evt->size.width, evt->size.height));
if (evt->size.width != DWIDTH || evt->size.height != DHEIGHT) {
GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Dektec Out] Bad resize (%ux%u) received. Expected %dx%d.\n", evt->size.width, evt->size.height, DWIDTH, DHEIGHT));
if (evt->size.width*evt->size.height > DWIDTH*DHEIGHT)
return GF_BAD_PARAM;
}
return GF_OK;
}
}
return GF_OK;
}
static GF_Err Dektec_resize(GF_VideoOutput *dr, u32 w, u32 h)
{
DtContext *dtc = (DtContext*)dr->opaque;
if (dtc->pixels) gf_free(dtc->pixels);
if (dtc->pixels_UYVY) gf_free(dtc->pixels_UYVY);
dtc->width = w;
dtc->height = h;
dtc->pixels = (char*)gf_malloc(dtc->bpp * w * h);
if (!dtc->pixels) return GF_OUT_OF_MEM;
memset(dtc->pixels, 0, dtc->bpp * w * h);
dtc->pixels_UYVY = (unsigned char*)gf_malloc(2 * w * h);
if (!dtc->pixels_UYVY) return GF_OUT_OF_MEM;
memset(dtc->pixels_UYVY, 0, 2 * w * h);
return GF_OK;
}
GF_Err Dektec_Setup(GF_VideoOutput *dr, void *os_handle, void *os_display, u32 init_flags)
{
GF_LOG(GF_LOG_DEBUG, GF_LOG_MODULE, ("[Dektec Out] Dektec_Setup\n"));
DtContext *dtc = (DtContext*)dr->opaque;
dtc->bpp = 3;
dtc->pixel_format = GF_PIXEL_YV12;
dtc->isSending = false;
Dektec_resize(dr, DWIDTH, DHEIGHT);
int port = 1;
const char *opt;
opt = gf_modules_get_option((GF_BaseInterface *)dr, "DektecVideo", "SDIOutput");
if (opt) {
port = atoi(opt);
GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Dektec Out] Using port %d (%s)\n", port, opt));
} else {
GF_LOG(GF_LOG_INFO, GF_LOG_MODULE, ("[Dektec Out] No port specified, using default port: %d\n", port));
}
DtDevice *dvc = dtc->dvc;
DtFrameBuffer *dtf = dtc->dtf;
DTAPI_RESULT res;
res = dvc->AttachToType(2154);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] No DTA-2154 in system: %s\n", DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
res = dvc->SetIoConfig(port, DTAPI_IOCONFIG_IODIR, DTAPI_IOCONFIG_OUTPUT, DTAPI_IOCONFIG_OUTPUT);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't set I/O config for the device: %s\n", DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
res = dtf->AttachToOutput(dvc, port, 0);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't attach to port %d: %s\n", port, DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
int IoStdValue=-1, IoStdSubValue=-1;
res = DtapiVidStd2IoStd(DFORMAT, IoStdValue, IoStdSubValue);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Unknown VidStd: %s\n", DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
res = dtf->SetIoConfig(DTAPI_IOCONFIG_IOSTD, IoStdValue, IoStdSubValue);
if (tru && res != DTAPI_OK) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] Can't set I/O config: %s\n", DtapiResult2Str(res)));
return GF_BAD_PARAM;
}
dtc->frameNum = -1;
return GF_OK;
}
GF_VideoOutput *NewDektecVideoOutput()
{
GF_VideoOutput *driv = (GF_VideoOutput *) gf_malloc(sizeof(GF_VideoOutput));
memset(driv, 0, sizeof(GF_VideoOutput));
GF_REGISTER_MODULE_INTERFACE(driv, GF_VIDEO_OUTPUT_INTERFACE, "Dektec Video Output", "gpac distribution")
DtDevice *dvc = new DtDevice;
DtFrameBuffer *dtf = new DtFrameBuffer;
if (!dtf || !dvc) {
GF_LOG(GF_LOG_ERROR, GF_LOG_MODULE, ("[Dektec Out] DTA API couldn't be initialized.\n"));
delete dvc;
delete dtf;
gf_free(driv);
return NULL;
}
DtContext *dtc = new DtContext;
memset(dtc, 0, sizeof(DtContext));
dtc->dvc = dvc;
dtc->dtf = dtf;
driv->opaque = (void*)dtc;
driv->Flush = Dektec_Flush;
driv->LockBackBuffer = Dektec_LockBackBuffer;
driv->Setup = Dektec_Setup;
driv->Shutdown = Dektec_Shutdown;
driv->ProcessEvent = Dektec_ProcessEvent;
driv->Blit = Dektec_Blit;
driv->hw_caps |= GF_VIDEO_HW_HAS_YUV_OVERLAY | GF_VIDEO_HW_HAS_YUV;
return driv;
}
void DeleteDektecVideoOutput(void *ifce)
{
GF_VideoOutput *driv = (GF_VideoOutput *) ifce;
DtContext *dtc = (DtContext*)driv->opaque;
gf_free(dtc->pixels);
gf_free(dtc->pixels_UYVY);
delete(dtc->dtf);
delete(dtc->dvc);
delete(dtc);
gf_free(driv);
}
#ifndef GPAC_STANDALONE_RENDER_2D
GPAC_MODULE_EXPORT
const u32 *QueryInterfaces()
{
static u32 si [] = {
GF_VIDEO_OUTPUT_INTERFACE,
0
};
return si;
}
GPAC_MODULE_EXPORT
GF_BaseInterface *LoadInterface(u32 InterfaceType)
{
if (InterfaceType == GF_VIDEO_OUTPUT_INTERFACE) return (GF_BaseInterface *) NewDektecVideoOutput();
return NULL;
}
GPAC_MODULE_EXPORT
void ShutdownInterface(GF_BaseInterface *ifce)
{
switch (ifce->InterfaceType) {
case GF_VIDEO_OUTPUT_INTERFACE:
DeleteDektecVideoOutput((GF_VideoOutput *)ifce);
break;
}
}
GPAC_MODULE_STATIC_DECLARATION( dektec_out )
#endif
}