Mercurial > mplayer.hg
changeset 17600:6fa1149d8c80
experimental film2pal and ntsc2pal soft teleciner
author | nicodvb |
---|---|
date | Sun, 12 Feb 2006 11:04:12 +0000 |
parents | c7d0f6322721 |
children | 515c7658aa71 |
files | libmpdemux/muxer_mpeg.c |
diffstat | 1 files changed, 68 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpdemux/muxer_mpeg.c Sun Feb 12 10:51:04 2006 +0000 +++ b/libmpdemux/muxer_mpeg.c Sun Feb 12 11:04:12 2006 +0000 @@ -145,6 +145,7 @@ typedef struct { int has_pts, has_dts, pes_is_aligned, type, is_late, min_pes_hlen, psm_fixed; + int real_framerate, delay_rff; uint64_t pts, last_pts, last_dts, dts, init_pts, init_dts, size, frame_duration, delta_pts, nom_delta_pts, frame_size, last_saved_pts; uint32_t buffer_size; uint8_t pes_priv_headers[4], has_pes_priv_headers; //for A52 and LPCM @@ -163,6 +164,8 @@ mp_mpeg_header_t picture; } muxer_headers_t; +#define PULLDOWN32 1 +#define TELECINE_FILM2PAL 2 m_option_t mpegopts_conf[] = { {"format", &(conf_mux), CONF_TYPE_STRING, 0, 0 ,0, NULL}, @@ -181,7 +184,8 @@ {"drop", &conf_drop, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"tsaf", &conf_ts_allframes, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"skip_padding", &conf_skip_padding, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - {"telecine", &conf_telecine, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"telecine", &conf_telecine, CONF_TYPE_FLAG, 0, 0, PULLDOWN32, NULL}, + {"film2pal", &conf_telecine, CONF_TYPE_FLAG, 0, 0, TELECINE_FILM2PAL, NULL}, {NULL, NULL, 0, 0, 0, 0, NULL} }; @@ -1788,7 +1792,9 @@ static int soft_telecine(muxer_headers_t *vpriv, uint8_t *fps_ptr, uint8_t *se_ptr, uint8_t *pce_ptr, int n) { uint8_t fps, tff, rff; + int period; + period = (vpriv->telecine == TELECINE_FILM2PAL) ? 12 : 4; if(fps_ptr != NULL) { fps = *fps_ptr & 0x0f; @@ -1798,8 +1804,16 @@ vpriv->telecine = 0; return 0; } + if(vpriv->telecine == TELECINE_FILM2PAL) + { + *fps_ptr = (*fps_ptr & 0xf0) | FRAMERATE_25; + vpriv->nom_delta_pts = parse_fps(25.0); + } + else + { *fps_ptr = (*fps_ptr & 0xf0) | (fps + 3); vpriv->nom_delta_pts = parse_fps((fps + 3) == FRAMERATE_2997 ? 30000.0/1001.0 : 30.0); + } } //in pce_ptr starting from bit 0 bit 24 is tff, bit 30 is rff, @@ -1821,19 +1835,66 @@ if(! vpriv->vframes) //initial value of tff vpriv->trf = (pce_ptr[3] >> 6) & 0x2; - while(n < 0) n+=4; - vpriv->trf = (vpriv->trf + n) % 4; + while(n < 0) n+=period; + vpriv->trf = (vpriv->trf + n) % period; //sets curent tff/rff bits + if(vpriv->telecine == TELECINE_FILM2PAL) + { + //repeat 1 field every 12 frames + int rest1 = (vpriv->trf % period) == 11; + int rest2 = vpriv->vframes % 999; + + rff = 0; + if(rest1) + rff = 2; + + if(vpriv->real_framerate == FRAMERATE_23976) + { + //we have to inverse the 1/1000 framedrop, repeating two fields in a sequence of 999 frames + //486 and 978 are ideal because they are halfway in the sequence + //additionally x % 12 == 6 (halfway between two frames with rff set) + //and enough in advance to check if rest1 is valid too, + //so we can delay the setting of rff to current_frame+3 with no risk to leave the + //current sequence unpatched + if(rest2 == 486 || rest2 == 978) + { + if(rest1) + { + vpriv->delay_rff = 4; //delay of 3 frames the setting, so we don't have 2 consecutive rff + mp_msg(MSGT_MUXER, MSGL_V, "\r\nDELAYED: %d\r\n", rest2); + } + else + rff = 2; + } + + if(!rest1 && vpriv->delay_rff) + { + vpriv->delay_rff--; + if(vpriv->delay_rff == 1) + { + rff = 2; + vpriv->delay_rff = 0; + mp_msg(MSGT_MUXER, MSGL_V, "\r\nRECOVERED: %d\r\n", rest2); + } + } + } + + pce_ptr[3] = (pce_ptr[3] & 0xfd) | rff; + } + else + { tff = (vpriv->trf & 0x2) ? 0x80 : 0; rff = (vpriv->trf & 0x1) ? 0x2 : 0; + pce_ptr[3] = (pce_ptr[3] & 0x7d) | tff | rff; + } + pce_ptr[4] |= 0x80; //sets progressive frame mp_msg(MSGT_MUXER, MSGL_DBG2, "\nTRF: %d, TFF: %d, RFF: %d, n: %d\n", vpriv->trf, tff >> 7, rff >> 1, n); - pce_ptr[3] = (pce_ptr[3] & 0x7d) | tff | rff; - pce_ptr[4] |= 0x80; //sets progressive frame + if(! vpriv->vframes) mp_msg(MSGT_MUXER, MSGL_INFO, "\nENABLED SOFT TELECINING, FPS=%s, INITIAL PATTERN IS TFF:%d, RFF:%d\n", - framerates[fps+3], tff >> 7, rff >> 1); + framerates[(vpriv->telecine == TELECINE_FILM2PAL) ? FRAMERATE_25 : fps+3], tff >> 7, rff >> 1); return 1; } @@ -1861,6 +1922,7 @@ if(s->buffer[3] == 0xb3) //sequence { fps_ptr = &(s->buffer[7]); + spriv->real_framerate = *fps_ptr & 0x0f; mp_header_process_sequence_header(&(spriv->picture), &(s->buffer[4])); spriv->delta_pts = spriv->nom_delta_pts = parse_fps(spriv->picture.fps);