Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/driver/hardware-boxpro.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,11 @@ void Display_UI() {
pthread_mutex_unlock(&hardware_mutex);
}

// The BoxPRO UI already runs at 720p60, which suits 60 and 90 fps DVR files,
// so there is nothing to retime here.
void Display_UI_SetRefresh(int hz) {
}

void HDZero_open(int bw) {
if (bw != g_hw_stat.hdz_bw) // reopen with different bw
HDZero_Close();
Expand Down
35 changes: 35 additions & 0 deletions src/driver/hardware-goggle.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,41 @@ void Display_UI() {
pthread_mutex_unlock(&hardware_mutex);
}

// Retime the UI output for DVR playback. 60Hz keeps the 1080p UI on the
// same 148.5MHz pixel clock, so the OLED and FPGA settings from
// Display_UI_init stay valid. 90Hz reuses the vdpo timing, clock phases and
// OLED mode proven by the live 720p90 path (the FPGA stays on the UI input).
// 0 restores the stock menu timing with a full Display_UI_init.
void Display_UI_SetRefresh(int hz) {
int tmg = (hz == 90) ? VDPO_TMG_720P90 : (hz == 60) ? VDPO_TMG_1080P60 : VDPO_TMG_1080P50;

pthread_mutex_lock(&hardware_mutex);
if ((g_hw_stat.source_mode == SOURCE_MODE_UI) && (g_hw_stat.vdpo_tmg != tmg)) {
screen.display(0);

if (hz == 90) {
system_exec("dispw -s vdpo 720p90");
g_hw_stat.vdpo_tmg = VDPO_TMG_720P90;
vclk_phase_set(VIDEO_SOURCE_HDZERO_IN_720P90, 0);
pclk_phase_set(VIDEO_SOURCE_HDZERO_IN_720P90);
screen.vtmg(1);
system_exec("aww 0x0300b084 0x00001565"); // Set vdpo clock driver strength to level 2. Refer datasheet 12.7.5.11
system_exec("aww 0x06542018 0x00000044"); // disable horizontal chroma FIR filter.
} else if (hz == 60) {
system_exec("dispw -s vdpo 1080p60");
g_hw_stat.vdpo_tmg = VDPO_TMG_1080P60;
system_exec("aww 0x0300b084 0x00001565"); // Set vdpo clock driver strength to level 2. Refer datasheet 12.7.5.11
system_exec("aww 0x06542018 0x00000044"); // disable horizontal chroma FIR filter.
} else {
Display_UI_init();
}

screen.display(1);
LOGI("Display_UI_SetRefresh: %dHz", hz ? hz : 50);
}
pthread_mutex_unlock(&hardware_mutex);
}

void Display_720P60_50_t(int mode, uint8_t is_43) // fps: 0=50, 1=60
{
screen.display(0);
Expand Down
37 changes: 37 additions & 0 deletions src/driver/hardware-goggle2.c
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,43 @@ void Display_UI() {
pthread_mutex_unlock(&hardware_mutex);
}

// Retime the UI output for DVR playback. 60Hz keeps the 1080p UI on the
// same 148.5MHz pixel clock, so the OLED and FPGA settings from
// Display_UI_init stay valid. 90Hz reuses the vdpo timing, clock phases and
// OLED mode proven by the live 720p90 path (the FPGA stays on the UI input).
// 0 restores the stock menu timing with a full Display_UI_init.
void Display_UI_SetRefresh(int hz) {
int tmg = (hz == 90) ? VDPO_TMG_720P90 : (hz == 60) ? VDPO_TMG_1080P60 : VDPO_TMG_1080P50;

pthread_mutex_lock(&hardware_mutex);
if ((g_hw_stat.source_mode == SOURCE_MODE_UI) && (g_hw_stat.vdpo_tmg != tmg)) {
screen.display(0);

if (hz == 90) {
system_exec("dispw -s vdpo 720p90");
g_hw_stat.vdpo_tmg = VDPO_TMG_720P90;
system_exec("aww 0x0300b340 0x00000008");
vclk_phase_set(VIDEO_SOURCE_HDZERO_IN_720P90, 0);
pclk_phase_set(VIDEO_SOURCE_HDZERO_IN_720P90);
screen.vtmg(1);
system_exec("aww 0x0300b084 0x00003fff"); // Set vdpo clock driver strength to level 2. Refer datasheet 12.7.5.11
system_exec("aww 0x06542018 0x00000044"); // disable horizontal chroma FIR filter.
} else if (hz == 60) {
system_exec("dispw -s vdpo 1080p60");
g_hw_stat.vdpo_tmg = VDPO_TMG_1080P60;
system_exec("aww 0x0300b340 0x00000008");
system_exec("aww 0x0300b084 0x00003fff"); // Set vdpo clock driver strength to level 2. Refer datasheet 12.7.5.11
system_exec("aww 0x06542018 0x00000044"); // disable horizontal chroma FIR filter.
} else {
Display_UI_init();
}

screen.display(1);
LOGI("Display_UI_SetRefresh: %dHz", hz ? hz : 50);
}
pthread_mutex_unlock(&hardware_mutex);
}

void Display_720P60_50_t(int mode, uint8_t is_43) // fps: 0=50, 1=60
{
screen.display(0);
Expand Down
1 change: 1 addition & 0 deletions src/driver/hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ void Source_HDMI_in();
void Source_AV(bool is_av_in);
void Display_UI_init();
void Display_UI();
void Display_UI_SetRefresh(int hz); // retime the UI output for DVR playback (60 = 1080p60, 90 = 720p90); 0 restores the default UI timing

void Display_720P90(int mode);
void Display_720P60_50(int mode, uint8_t is_43);
Expand Down
3 changes: 2 additions & 1 deletion src/player/awdmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,9 @@ AwdmxContext_t *awdmx_open(char *sFile, CB_onDmxEof cbOnEof, void *context) {
dmxCtx->width = DemuxMediaInfo.mVideoStreamInfo[nIndex].mWidth;
dmxCtx->height = DemuxMediaInfo.mVideoStreamInfo[nIndex].mHeight;
dmxCtx->codecType = DemuxMediaInfo.mVideoStreamInfo[nIndex].mCodecType;
dmxCtx->fpsX1000 = DemuxMediaInfo.mVideoStreamInfo[nIndex].mFrameRate;
dmxCtx->msDuration = DemuxMediaInfo.mDuration;
LOGD("stream info %dx%d", DemuxMediaInfo.mVideoStreamInfo[nIndex].mWidth, DemuxMediaInfo.mVideoStreamInfo[nIndex].mHeight);
LOGD("stream info %dx%d @%dmfps", DemuxMediaInfo.mVideoStreamInfo[nIndex].mWidth, DemuxMediaInfo.mVideoStreamInfo[nIndex].mHeight, dmxCtx->fpsX1000);

if (DemuxMediaInfo.mAudioNum > 0) {
nIndex = DemuxMediaInfo.mAudioIndex;
Expand Down
1 change: 1 addition & 0 deletions src/player/awdmx.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ typedef struct
int videoNum;
uint16_t width;
uint16_t height;
int fpsX1000; // video frame rate * 1000, 0 if unknown
PAYLOAD_TYPE_E codecType;

int audioNum;
Expand Down
33 changes: 31 additions & 2 deletions src/player/media.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "adec2ao.h"
#include "awdmx.h"
#include "driver/hardware.h"
#include "gogglemsg.h"
#include "vdec2vo.h"
#include "version.h"
Expand Down Expand Up @@ -66,6 +67,7 @@ typedef struct
pthread_mutex_t mutex;

int playingTime; // ms
int retimedHz; // nonzero while the UI output is retimed for this file
} PlayContext_t;

static int play_start(PlayContext_t *playCtx) {
Expand Down Expand Up @@ -238,17 +240,38 @@ media_t *media_instantiate(char *filename, notify_cb_t notify) {
goto failed;
} else {
Vdec2VoParams_t vvParams;
int voWidth = VO_WIDTH;
int voHeight = VO_HEIGHT;
memset(&vvParams, 0, sizeof(vvParams));

#if PLAY_HDZERO && (defined(HDZGOGGLE) || defined(HDZGOGGLE2))
// The menu UI drives the panel at 1080p50, which drops frames of
// 60/90fps DVR files unevenly. Retime for the duration of playback:
// 90fps files reuse the live-mode 720p90 timing so every frame is
// shown, 60fps files keep the 1080p UI on the same pixel clock.
int fps = (playCtx->dmx->fpsX1000 + 500) / 1000;
if (fps >= 80) {
playCtx->retimedHz = 90;
voWidth = 1280;
voHeight = 720;
} else if (fps >= 55) {
playCtx->retimedHz = 60;
}
if (playCtx->retimedHz) {
LOGD("retiming display to %dHz for %dfps file", playCtx->retimedHz, fps);
Display_UI_SetRefresh(playCtx->retimedHz);
}
#endif

vvParams.initRotation = 0;
vvParams.pixelFormat = MM_PIXEL_FORMAT_YVU_PLANAR_420;

vvParams.vdec.codecType = playCtx->dmx->codecType;
vvParams.vdec.width = playCtx->dmx->width;
vvParams.vdec.height = playCtx->dmx->height;

vvParams.vo.width = VO_WIDTH;
vvParams.vo.height = VO_HEIGHT;
vvParams.vo.width = voWidth;
vvParams.vo.height = voHeight;
vvParams.vo.intfType = VO_intfTYPE;
vvParams.vo.intfSync = VO_intfSYNC;
vvParams.vo.uiChn = VO_uiCHN;
Expand Down Expand Up @@ -288,6 +311,9 @@ media_t *media_instantiate(char *filename, notify_cb_t notify) {
adec2ao_deinitSys(playCtx->aa);
vdec2vo_deinitSys(playCtx->vv);
awdmx_close(playCtx->dmx);
if (playCtx->retimedHz) {
Display_UI_SetRefresh(0);
}
pthread_mutex_destroy(&playCtx->mutex);
free(playCtx);
LOGD("exit done");
Expand All @@ -305,6 +331,9 @@ void media_exit(media_t *media) {
adec2ao_deinitSys(playCtx->aa);
vdec2vo_deinitSys(playCtx->vv);
awdmx_close(playCtx->dmx);
if (playCtx->retimedHz) {
Display_UI_SetRefresh(0);
}
pthread_mutex_destroy(&playCtx->mutex);
free(media->context);
free(media);
Expand Down
7 changes: 5 additions & 2 deletions src/record/ffpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,11 @@ int ffpack_newVideoStream(FFPack_t* ff, uint16_t programId, FFStreamParameters_t
stream->r_frame_rate.den = 0;//1;
stream->avg_frame_rate.num = param->video.fps;
stream->avg_frame_rate.den = 1;
stream->time_base.num = 1;//0;
stream->time_base.den = param->video.fps;//100000;//1; //10us
/* a 1/fps time base rounds every capture timestamp to a whole frame
* slot (and collides when the real rate drifts from the configured
* fps), baking judder into the file; 90kHz keeps timestamps exact */
stream->time_base.num = 1;
stream->time_base.den = 90000;
cp->codec_type = param->mediaType;
cp->codec_id = param->codecId;
cp->width = param->video.width;
Expand Down