[mythtv] [PATCH] Add AFD support for aspect 'magic'
Neale Swinnerton
mythtv-dev.spam at isismanor.com
Sun Jun 5 22:47:45 UTC 2005
Here's an updated version of the patch. It's a little cleaner, and I
fixed some stupid errors I made, that led to SEGV with certain
aspect/afd combos.
I'm particularly interested to see how this works with a 4_3_sp_14_9 AFD
(13) in a 16:9 frame. The correct behaviour is to crop a little of the
top and bottom and still leave the image pillarboxed. I suspect this
will cause problems with hardware scaling, because the size will be odd.
Neale.
Neale Swinnerton wrote:
> The Active Format Descriptor (AFD) is set by some broadcasters like ITV1
> and CH4 in the UK in their DVB-T streams. This signals what the format
> of the video is, and along with the aspect ratio of the video stream and
> your display it can resize the video 'better'.
>
> This patch adds support for this to myth. To enable it go to
> Utilities/Setup->Settings->TV Settings->Playback and set aspect override
> to AFD.
>
> When playing back streams that have AFD set you should see the image
> scaled better. ie. it will apply letterboxing/pillarboxing as
> appropriate, Shoot & Protect areas should be honoured.
>
> AFD has some caveats:
> + Only works where the MPEG Stream is either 4:3 or 16:9
> + Only works where your display is either 4:3 or 16:9
>
> Note that if you don't have GuiSizeForTv set the aspect ratio comes from
> the DisplaySize option in your xorg.conf, if GuiSizeForTv is set myth
> calculates the aspect ratio of your screen with the following code
>
> void VideoOutputXv::InitDisplayMeasurements(uint width, uint height)
> {
> <SNIP/>
> int w = DisplayWidth(XJ_disp, XJ_screen_num);
> int h = DisplayHeight(XJ_disp, XJ_screen_num);
> int gui_w = w, gui_h = h;
> gContext->GetResolutionSetting("Gui", gui_w, gui_h);
> if (gui_w)
> w_mm = w_mm * gui_w / w;
> if (gui_h)
> h_mm = h_mm * gui_h / h;
>
> display_aspect = (float)w_mm/h_mm;
> <SNIP/>
> }
>
> w_mm/h_mm is the width/height of your screen in mm as reported by X (ie.
> the values passed via DisplaySize option), for me this means I need a
> gui size of 1024x576 to get my display aspect to 1.78.
>
> I left debug output switched on in the patch, so you will see what value
> myth is calculating for your aspect ratio....
>
> TODO: I'm not sure that the size calculations for the various
> combinations are correct, it seems to work for my limited testing on
> ITV1 / Ch 4. I'm trying to find a test stream to test this out.
>
> http://www.rsd.de/www/dev_center.nsf/frameset?OpenAgent&website=com&content=/www/dev_center.nsf/html/DV-TCMuseafd
>
> looks ideal, but I don't have access to that sort of kit and I haven't
> found an easy way to generate such a stream. Any ideas?
>
> TODO: It seems reasonable to add a 'AFD or Fill' mode that falls back to
> Fill Mode if the AFD isn't set. This should be easy, but the code needs
> a rejig to allow the fill code to be common to both modes.
>
> TODO: Implement WSS line 23 switching in the Unichrome driver, to make
> this really slick. I doubt this is easily possible, maybe some boards
> support it (
> http://www.commell.com.tw/Product/Peripheral/MiniAGP/MA-HDTV.htm )
>
> enjoy...
>
> Neale.
>
>
>
>
> ------------------------------------------------------------------------
>
> diff -bBuwr mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.cpp mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.cpp
> --- mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.cpp 2005-05-24 03:59:13.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.cpp 2005-06-02 22:37:21.000000000 +0100
> @@ -455,6 +455,7 @@
>
> videofiltersLock.lock();
> videoOutput->InputChanged(video_width, video_height, video_aspect);
> + videoOutput->SetAfdMode(video_afd_mode);
> if (videoOutput->IsErrored())
> {
> VERBOSE(VB_IMPORTANT, "ReinitVideo(): videoOutput->IsErrored()");
> @@ -531,13 +532,13 @@
>
> void NuppelVideoPlayer::SetVideoParams(int width, int height, double fps,
> int keyframedistance, float aspect,
> - FrameScanType scan, bool reinit)
> + int afd_mode, FrameScanType scan, bool reinit)
> {
> if (width == 0 || height == 0 || isnan(aspect) || isnan(fps))
> return;
>
> if (video_width == width && video_height == height &&
> - aspect == video_aspect && fps == video_frame_rate)
> + aspect == video_aspect && afd_mode == video_afd_mode && fps == video_frame_rate)
> {
> return;
> }
> @@ -564,6 +565,8 @@
> commDetect->SetVideoParams(aspect);
> }
>
> + video_afd_mode = afd_mode;
> +
> if (reinit)
> ReinitVideo();
>
> diff -bBuwr mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.h mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.h
> --- mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.h 2005-05-05 03:51:15.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.h 2005-06-02 22:36:30.000000000 +0100
> @@ -156,7 +156,8 @@
> void SetKeyframeDistance(int keyframedistance);
> void SetVideoParams(int width, int height, double fps,
> int keyframedistance, float aspect = 1.33333,
> - FrameScanType scan = kScan_Ignore, bool reinit = false);
> + int afd_code = kAfd_Unset, FrameScanType scan = kScan_Ignore,
> + bool reinit = false);
> void SetAudioParams(int bps, int channels, int samplerate);
> void SetEffDsp(int dsprate);
> void SetFileLength(int total, int frames);
> @@ -295,6 +296,7 @@
> int video_size;
> double video_frame_rate;
> float video_aspect;
> + int video_afd_mode;
> FrameScanType m_scan;
> bool m_double_framerate;
> bool m_can_double;
> diff -bBuwr mythtv-20050530/libs/libmythtv/avformatdecoder.cpp mythtv-20050530.patched/libs/libmythtv/avformatdecoder.cpp
> --- mythtv-20050530/libs/libmythtv/avformatdecoder.cpp 2005-05-23 21:39:12.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/avformatdecoder.cpp 2005-06-03 07:19:11.000000000 +0100
> @@ -553,6 +553,7 @@
> current_width = enc->width;
> current_height = enc->height;
> current_aspect = aspect_ratio;
> + current_afd_mode = enc->dtg_active_format;
>
> enc->opaque = NULL;
> enc->get_buffer = NULL;
> @@ -603,7 +604,7 @@
> avcodec_align_dimensions(enc, &align_width, &align_height);
>
> m_parent->SetVideoParams(align_width, align_height, fps,
> - keyframedist, aspect_ratio, kScan_Detect);
> + keyframedist, aspect_ratio, current_afd_mode, kScan_Detect);
> }
>
> #ifdef USING_XVMC
> @@ -1158,10 +1159,12 @@
>
> float aspect = GetMpegAspect(context, aspectratioinfo,
> width, height);
> + int afd_mode = context->dtg_active_format;
>
> if (width < 2500 && height < 2000 &&
> (CheckVideoParams(width, height) ||
> - aspect != current_aspect))
> + aspect != current_aspect ||
> + afd_mode != current_afd_mode))
> {
> int align_width = width;
> int align_height = height;
> @@ -1174,11 +1177,12 @@
>
> m_parent->SetVideoParams(align_width,
> align_height, fps,
> - keyframedist, aspect,
> + keyframedist, aspect, afd_mode,
> kScan_Detect, true);
> current_width = width;
> current_height = height;
> current_aspect = aspect;
> + current_afd_mode = afd_mode;
>
> if (d->mpeg2dec)
> d->ResetMPEG2();
> diff -bBuwr mythtv-20050530/libs/libmythtv/decoderbase.h mythtv-20050530.patched/libs/libmythtv/decoderbase.h
> --- mythtv-20050530/libs/libmythtv/decoderbase.h 2005-04-27 20:32:49.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/decoderbase.h 2005-06-03 07:16:20.000000000 +0100
> @@ -87,6 +87,7 @@
> int current_width;
> int current_height;
> float current_aspect;
> + int current_afd_mode;
>
> long long framesPlayed;
> long long framesRead;
> diff -bBuwr mythtv-20050530/libs/libmythtv/tv_play.cpp mythtv-20050530.patched/libs/libmythtv/tv_play.cpp
> --- mythtv-20050530/libs/libmythtv/tv_play.cpp 2005-05-27 01:59:21.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/tv_play.cpp 2005-06-02 22:09:40.000000000 +0100
> @@ -3476,6 +3476,7 @@
> case kLetterbox_16_9_Zoom: text = tr("16:9 Zoom"); break;
> case kLetterbox_16_9_Stretch: text = tr("16:9 Stretch"); break;
> case kLetterbox_Fill: text = tr("Fill"); break;
> + case kLetterbox_Afd: text = tr("Active Format"); break;
> default: text = tr("Off"); break;
> }
>
> diff -bBuwr mythtv-20050530/libs/libmythtv/videooutbase.cpp mythtv-20050530.patched/libs/libmythtv/videooutbase.cpp
> --- mythtv-20050530/libs/libmythtv/videooutbase.cpp 2005-05-26 03:17:04.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/videooutbase.cpp 2005-06-04 01:09:38.365803256 +0100
> @@ -136,6 +136,7 @@
> VideoOutput::VideoOutput()
> {
> letterbox = kLetterbox_Off;
> + afd_mode = kAfd_Unset;
>
> framesPlayed = 0;
>
> @@ -359,7 +360,8 @@
> {
> default:
> case kLetterbox_Off:
> - case kLetterbox_Fill: XJ_aspect = videoAspect;
> + case kLetterbox_Fill:
> + case kLetterbox_Afd: XJ_aspect = videoAspect;
> break;
>
> case kLetterbox_4_3:
> @@ -487,6 +489,9 @@
> yoff = imgy;
> width = imgw;
> height = imgh;
> + float displayAspect = GetDisplayAspect();
> + bool displayAspectIs_16_9 = (fabs(displayAspect - 1.777777) < 0.05);
> + bool videoAspectIs_16_9 = (fabs(XJ_aspect - 1.777777) < 0.05);
>
> switch (letterbox)
> {
> @@ -504,19 +509,68 @@
> case kLetterbox_Fill:
> if (GetDisplayAspect() > XJ_aspect)
> {
> - int pixDisplayed = int(((XJ_aspect / GetDisplayAspect()) * imgh) + 0.5);
> + int pixDisplayed = int(((XJ_aspect /displayAspect) * imgh) + 0.5);
>
> height = pixDisplayed;
> yoff = (imgh - pixDisplayed) / 2;
> }
> else
> {
> - int pixDisplayed = int(((GetDisplayAspect() / XJ_aspect) * imgw) + 0.5);
> + int pixDisplayed = int(((displayAspect / XJ_aspect) * imgw) + 0.5);
>
> width = pixDisplayed;
> xoff = (imgw - pixDisplayed) / 2;
> }
> break;
> + case kLetterbox_Afd:
> + if ( videoAspectIs_16_9 ) {
> + switch (afd_mode)
> + {
> + case kAfd_Unset:
> + case kAfd_Same:
> + case kAfd_16_9:
> + case kAfd_14_9:
> + case kAfd_16_9_Sp_14_9:
> + case kAfd_Sp_4_3:
> + break;
> + case kAfd_4_3:
> + if (displayAspectIs_16_9) {
> + width *= 3/4;
> + xoff = width/6;
> + }
> + break;
> + case kAfd_4_3_Sp_14_9:
> + if (displayAspectIs_16_9) {
> + height *= 4/3;
> + yoff -= height/6;
> + width *= 3/4;
> + xoff += width/6;
> + }
> + break;
> + }
> + } else { // videoAspectIs_4_3
> + switch (afd_mode)
> + {
> + case kAfd_Unset:
> + case kAfd_16_9:
> + case kAfd_16_9_Sp_14_9:
> + break;
> + case kAfd_Same:
> + case kAfd_Sp_4_3:
> + if (displayAspectIs_16_9) {
> + width *= 3/4;
> + xoff += width/6;
> + }
> + break;
> + case kAfd_4_3_Sp_14_9:
> + if (displayAspectIs_16_9) {
> + width = width*4/3;
> + yoff -= height/6;
> + }
> + break;
> + }
> + }
> + break;
> default:
> break;
> }
> @@ -532,6 +586,7 @@
> {
> int yoff, xoff;
> float displayAspect;
> + int displayAspectIs_16_9, videoAspectIs_16_9;
>
> // Preset all image placement and sizing variables.
> imgx = 0; imgy = 0;
> @@ -544,6 +599,8 @@
>
> // Get display aspect and correct for rounding errors
> displayAspect = GetDisplayAspect();
> + displayAspectIs_16_9 = (fabs(displayAspect - 1.777777) > 0.05)?0:1;
> + videoAspectIs_16_9 = (fabs(XJ_aspect - 1.333333) > 0.05)?0:1;
>
> // Check if close to 4:3
> if(fabs(displayAspect - 1.333333) < 0.05)
> @@ -659,11 +716,61 @@
> // account the aspect ratios of both the video as well as the actual
> // screen to allow proper letterboxing to take place.
>
> - //cout << "XJ aspect " << XJ_aspect << endl;
> - //cout << "Display aspect " << GetDisplayAspect() << endl;
> - //printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff,
> - // dispyoff);
> -
> + cout << "XJ aspect " << XJ_aspect << endl;
> + cout << "Display aspect " << GetDisplayAspect() << endl;
> + cout << "AFD " << afd_mode << endl;
> + printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff,
> + dispyoff);
> +
> + if ( letterbox == kLetterbox_Afd ){
> + if ( videoAspectIs_16_9 ) {
> + switch (afd_mode)
> + {
> + case kAfd_Unset:
> + case kAfd_Same:
> + case kAfd_16_9:
> + case kAfd_14_9:
> + case kAfd_16_9_Sp_14_9:
> + case kAfd_Sp_4_3:
> + break;
> + case kAfd_4_3:
> + if (displayAspectIs_16_9) {
> + dispwoff = dispwoff*3/4;
> + dispxoff += (dispwoff/6);
> + }
> + break;
> + case kAfd_4_3_Sp_14_9:
> + if (displayAspectIs_16_9) {
> + disphoff = disphoff*4/3;
> + dispyoff -= (disphoff/6);
> + dispwoff = (dispwoff*3/4);
> + dispxoff += (dispwoff/6);
> + }
> + break;
> + }
> + } else { // videoAspectIs_4_3
> + switch (afd_mode)
> + {
> + case kAfd_Unset:
> + case kAfd_16_9:
> + case kAfd_16_9_Sp_14_9:
> + break;
> + case kAfd_Same:
> + case kAfd_Sp_4_3:
> + if (displayAspectIs_16_9) {
> + dispwoff = dispwoff*3/4;
> + dispxoff += (dispwoff/6);
> + }
> + break;
> + case kAfd_4_3_Sp_14_9:
> + if (displayAspectIs_16_9) {
> + dispyoff -= (disphoff/6);
> + disphoff = disphoff*4/3;
> + }
> + break;
> + }
> + }
> + }
> if ((fabs(displayAspect - XJ_aspect) / displayAspect) > 0.1){
> if(letterbox == kLetterbox_Fill){
> if (displayAspect > XJ_aspect)
> @@ -772,7 +880,6 @@
> //printf("After: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff,
> //dispyoff);
>
> -#if 0
> printf("VideoOutput::MoveResize:\n");
> printf("Img(%d,%d %d,%d)\n", imgx, imgy, imgw, imgh);
> printf("Disp(%d,%d %d,%d)\n", dispxoff, dispyoff, dispwoff, disphoff);
> @@ -783,7 +890,6 @@
> printf("XJ_aspect(%f)\n", XJ_aspect);
> printf("CDisplayAspect: %f\n", displayAspect);
> printf("Letterbox: %d\n", letterbox);
> -#endif
>
> VERBOSE(VB_PLAYBACK,
> QString("Image size. dispxoff %1, dispyoff: %2, dispwoff: %3, "
> diff -bBuwr mythtv-20050530/libs/libmythtv/videooutbase.h mythtv-20050530.patched/libs/libmythtv/videooutbase.h
> --- mythtv-20050530/libs/libmythtv/videooutbase.h 2005-05-26 03:17:04.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/videooutbase.h 2005-06-04 00:36:13.000000000 +0100
> @@ -105,9 +105,29 @@
> kLetterbox_16_9_Zoom,
> kLetterbox_16_9_Stretch,
> kLetterbox_Fill,
> + kLetterbox_Afd,
> kLetterbox_END
> };
>
> +/* Active Format Description(AFD) is set in DVB Streams.
> + * By considering both the aspect ratio and the AFD it
> + * is posible to determine how to present the image in the
> + * correct manner.
> + * See http://www.dtg.org.uk/publications/books/afd.pdf
> + * for the gory details
> + */
> +enum AfdMode {
> + kAfd_Unset = 0,
> + kAfd_Same = 8,
> + kAfd_4_3 = 9,
> + kAfd_16_9 = 10,
> + kAfd_14_9 = 11,
> + kAfd_4_3_Sp_14_9 = 13,
> + kAfd_16_9_Sp_14_9 = 14,
> + kAfd_Sp_4_3 = 15,
> + kAfd_END
> +};
> +
> enum FrameScanType {
> kScan_Ignore = -1,
> kScan_Progressive = 0,
> @@ -162,6 +182,8 @@
> int GetLetterbox(void) { return letterbox; }
> void ToggleLetterbox(int letterboxMode = kLetterbox_Toggle);
>
> + void SetAfdMode(int afd_mode) { this->afd_mode = afd_mode; };
> +
> // pass in null to use the pause frame, if it exists.
> virtual void ProcessFrame(VideoFrame *frame, OSD *osd,
> FilterChain *filterList,
> @@ -298,6 +321,7 @@
> int brightness, contrast, colour, hue;
>
> int letterbox;
> + int afd_mode;
>
> int PIPLocation;
>
> diff -bBuwr mythtv-20050530/programs/mythfrontend/globalsettings.cpp mythtv-20050530.patched/programs/mythfrontend/globalsettings.cpp
> --- mythtv-20050530/programs/mythfrontend/globalsettings.cpp 2005-05-28 01:48:30.000000000 +0100
> +++ mythtv-20050530.patched/programs/mythfrontend/globalsettings.cpp 2005-06-04 01:14:06.980231084 +0100
> @@ -1160,11 +1160,15 @@
> gc->addSelection(QObject::tr("16/9 Zoom"), "4");
> gc->addSelection(QObject::tr("16/9 Stretch"), "5");
> gc->addSelection(QObject::tr("Fill"), "6");
> + gc->addSelection(QObject::tr("AFD"), "7");
> gc->setHelpText(QObject::tr("This will override any aspect ratio in the "
> "recorded stream, the same as pressing the W Key "
> "during playback. "
> "Fill will \"fill\" the screen with the image clipping as required. "
> "Fill is useful when using 4:3 interlaced TV's for display."
> + "AFD will use the active format descriptor from the stream "
> + "to determine the appropriate display. "
> + "(UK ITV & Ch4 only?)"
> ));
> return gc;
> }
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> mythtv-dev mailing list
> mythtv-dev at mythtv.org
> http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev
-------------- next part --------------
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp,v
retrieving revision 1.474
diff -a -u -b -B -r1.474 NuppelVideoPlayer.cpp
--- libs/libmythtv/NuppelVideoPlayer.cpp 3 Jun 2005 04:05:22 -0000 1.474
+++ libs/libmythtv/NuppelVideoPlayer.cpp 5 Jun 2005 15:08:50 -0000
@@ -456,6 +456,7 @@
videofiltersLock.lock();
videoOutput->InputChanged(video_width, video_height, video_aspect);
+ videoOutput->SetAfdMode(video_afd_mode);
if (videoOutput->IsErrored())
{
VERBOSE(VB_IMPORTANT, "ReinitVideo(): videoOutput->IsErrored()");
@@ -532,13 +533,13 @@
void NuppelVideoPlayer::SetVideoParams(int width, int height, double fps,
int keyframedistance, float aspect,
- FrameScanType scan, bool reinit)
+ int afd_mode, FrameScanType scan, bool reinit)
{
if (width == 0 || height == 0 || isnan(aspect) || isnan(fps))
return;
if (video_width == width && video_height == height &&
- aspect == video_aspect && fps == video_frame_rate)
+ aspect == video_aspect && afd_mode == video_afd_mode && fps == video_frame_rate)
{
return;
}
@@ -565,6 +566,8 @@
commDetect->SetVideoParams(aspect);
}
+ video_afd_mode = afd_mode;
+
if (reinit)
ReinitVideo();
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.h,v
retrieving revision 1.180
diff -a -u -b -B -r1.180 NuppelVideoPlayer.h
--- libs/libmythtv/NuppelVideoPlayer.h 2 Jun 2005 22:41:10 -0000 1.180
+++ libs/libmythtv/NuppelVideoPlayer.h 5 Jun 2005 15:08:50 -0000
@@ -156,7 +156,8 @@
void SetKeyframeDistance(int keyframedistance);
void SetVideoParams(int width, int height, double fps,
int keyframedistance, float aspect = 1.33333,
- FrameScanType scan = kScan_Ignore, bool reinit = false);
+ int afd_code = kAfd_Unset, FrameScanType scan = kScan_Ignore,
+ bool reinit = false);
void SetAudioParams(int bps, int channels, int samplerate);
void SetEffDsp(int dsprate);
void SetFileLength(int total, int frames);
@@ -301,6 +302,7 @@
int video_size;
double video_frame_rate;
float video_aspect;
+ int video_afd_mode;
FrameScanType m_scan;
bool m_double_framerate;
bool m_can_double;
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/avformatdecoder.cpp,v
retrieving revision 1.151
diff -a -u -b -B -r1.151 avformatdecoder.cpp
--- libs/libmythtv/avformatdecoder.cpp 3 Jun 2005 18:21:36 -0000 1.151
+++ libs/libmythtv/avformatdecoder.cpp 5 Jun 2005 15:08:51 -0000
@@ -553,6 +553,7 @@
current_width = enc->width;
current_height = enc->height;
current_aspect = aspect_ratio;
+ current_afd_mode = enc->dtg_active_format;
enc->opaque = NULL;
enc->get_buffer = NULL;
@@ -603,7 +604,7 @@
avcodec_align_dimensions(enc, &align_width, &align_height);
m_parent->SetVideoParams(align_width, align_height, fps,
- keyframedist, aspect_ratio, kScan_Detect);
+ keyframedist, aspect_ratio, current_afd_mode, kScan_Detect);
}
#ifdef USING_XVMC
@@ -1158,10 +1159,12 @@
float aspect = GetMpegAspect(context, aspectratioinfo,
width, height);
+ int afd_mode = context->dtg_active_format;
if (width < 2500 && height < 2000 &&
(CheckVideoParams(width, height) ||
- aspect != current_aspect))
+ aspect != current_aspect ||
+ afd_mode != current_afd_mode))
{
int align_width = width;
int align_height = height;
@@ -1174,11 +1177,12 @@
m_parent->SetVideoParams(align_width,
align_height, fps,
- keyframedist, aspect,
+ keyframedist, aspect, afd_mode,
kScan_Detect, true);
current_width = width;
current_height = height;
current_aspect = aspect;
+ current_afd_mode = afd_mode;
if (d->mpeg2dec)
d->ResetMPEG2();
Index: libs/libmythtv/decoderbase.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/decoderbase.h,v
retrieving revision 1.28
diff -a -u -b -B -r1.28 decoderbase.h
--- libs/libmythtv/decoderbase.h 27 Apr 2005 19:32:49 -0000 1.28
+++ libs/libmythtv/decoderbase.h 5 Jun 2005 15:08:51 -0000
@@ -87,6 +87,7 @@
int current_width;
int current_height;
float current_aspect;
+ int current_afd_mode;
long long framesPlayed;
long long framesRead;
Index: libs/libmythtv/tv_play.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_play.cpp,v
retrieving revision 1.271
diff -a -u -b -B -r1.271 tv_play.cpp
--- libs/libmythtv/tv_play.cpp 2 Jun 2005 22:41:11 -0000 1.271
+++ libs/libmythtv/tv_play.cpp 5 Jun 2005 15:08:52 -0000
@@ -3568,6 +3568,7 @@
case kLetterbox_16_9_Zoom: text = tr("16:9 Zoom"); break;
case kLetterbox_16_9_Stretch: text = tr("16:9 Stretch"); break;
case kLetterbox_Fill: text = tr("Fill"); break;
+ case kLetterbox_Afd: text = tr("AFD"); break;
default: text = tr("Off"); break;
}
Index: libs/libmythtv/videooutbase.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/videooutbase.cpp,v
retrieving revision 1.74
diff -a -u -b -B -r1.74 videooutbase.cpp
--- libs/libmythtv/videooutbase.cpp 26 May 2005 02:17:04 -0000 1.74
+++ libs/libmythtv/videooutbase.cpp 5 Jun 2005 15:08:52 -0000
@@ -136,6 +136,7 @@
VideoOutput::VideoOutput()
{
letterbox = kLetterbox_Off;
+ afd_mode = kAfd_Unset;
framesPlayed = 0;
@@ -359,7 +360,8 @@
{
default:
case kLetterbox_Off:
- case kLetterbox_Fill: XJ_aspect = videoAspect;
+ case kLetterbox_Fill:
+ case kLetterbox_Afd: XJ_aspect = videoAspect;
break;
case kLetterbox_4_3:
@@ -487,6 +489,7 @@
yoff = imgy;
width = imgw;
height = imgh;
+ float displayAspect = GetDisplayAspect();
switch (letterbox)
{
@@ -502,21 +505,75 @@
xoff = imgw/8;
break;
case kLetterbox_Fill:
- if (GetDisplayAspect() > XJ_aspect)
+ if (displayAspect > XJ_aspect)
{
- int pixDisplayed = int(((XJ_aspect / GetDisplayAspect()) * imgh) + 0.5);
+ int pixDisplayed = int(((XJ_aspect /displayAspect) * imgh) + 0.5);
height = pixDisplayed;
yoff = (imgh - pixDisplayed) / 2;
}
else
{
- int pixDisplayed = int(((GetDisplayAspect() / XJ_aspect) * imgw) + 0.5);
+ int pixDisplayed = int(((displayAspect / XJ_aspect) * imgw) + 0.5);
width = pixDisplayed;
xoff = (imgw - pixDisplayed) / 2;
}
break;
+ case kLetterbox_Afd:
+ if ( AspectIs16_9(videoAspect) ) {
+ switch (afd_mode)
+ {
+ case kAfd_Unset:
+ case kAfd_Same:
+ case kAfd_16_9:
+ case kAfd_14_9:
+ case kAfd_16_9_Sp_14_9:
+ case kAfd_Sp_4_3:
+ break;
+ case kAfd_4_3:
+ if (AspectIs16_9(displayAspect)) {
+ width = (width*3)/4;
+ xoff += (width/6);
+ }
+ break;
+ case kAfd_4_3_Sp_14_9:
+ if (AspectIs16_9(displayAspect)) {
+ height = (height*4)/3;
+ yoff -= (height/6);
+ width = (width*3)/4;
+ xoff += (width/6);
+ }
+ break;
+ default:
+ break;
+ }
+ } else { // videoAspectIs4_3
+ switch (afd_mode)
+ {
+ case kAfd_Unset:
+ case kAfd_Same:
+ case kAfd_16_9:
+ case kAfd_14_9:
+ case kAfd_16_9_Sp_14_9:
+ break;
+ case kAfd_Sp_4_3:
+ if (AspectIs16_9(displayAspect)) {
+ width = (width*3)/4;
+ xoff += (width/6);
+ }
+ break;
+ case kAfd_4_3_Sp_14_9:
+ if (AspectIs16_9(displayAspect)) {
+ width = (width*9)/14;
+ xoff += (width*7)/8;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
default:
break;
}
@@ -546,11 +604,11 @@
displayAspect = GetDisplayAspect();
// Check if close to 4:3
- if(fabs(displayAspect - 1.333333) < 0.05)
+ if(AspectIs4_3(displayAspect))
displayAspect = 1.333333;
// Check if close to 16:9
- if(fabs(displayAspect - 1.777777) < 0.05)
+ if(AspectIs16_9(displayAspect))
displayAspect = 1.777777;
/*
@@ -658,12 +716,70 @@
// Manage aspect ratio and letterbox settings. Code should take into
// account the aspect ratios of both the video as well as the actual
// screen to allow proper letterboxing to take place.
+#if 0
+ cout << "XJ aspect " << XJ_aspect << endl;
+ cout << "Display aspect " << GetDisplayAspect() << endl;
+ cout << "AFD " << afd_mode << endl;
+ printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff,
+ dispyoff);
+#endif
- //cout << "XJ aspect " << XJ_aspect << endl;
- //cout << "Display aspect " << GetDisplayAspect() << endl;
- //printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff,
- // dispyoff);
+ if ( letterbox == kLetterbox_Afd ){
+
+ VERBOSE(VB_PLAYBACK,
+ QString("Applying AFD of %1, video aspect is %2, display aspect is %3").arg(afd_mode).arg(videoAspect).arg(displayAspect));
+ if ( AspectIs16_9(videoAspect) ) {
+ switch (afd_mode)
+ {
+ case kAfd_Unset:
+ case kAfd_Same:
+ case kAfd_16_9:
+ case kAfd_14_9:
+ case kAfd_16_9_Sp_14_9:
+ case kAfd_Sp_4_3:
+ break;
+ case kAfd_4_3:
+ if (AspectIs16_9(displayAspect)) {
+ dispwoff = (dispwoff*3)/4;
+ dispxoff += (dispwoff/6);
+ }
+ break;
+ case kAfd_4_3_Sp_14_9:
+ if (AspectIs16_9(displayAspect)) {
+ disphoff = (disphoff*4)/3;
+ dispyoff -= (disphoff/6);
+ dispwoff = (dispwoff*3/4);
+ dispxoff += (dispwoff/6);
+ }
+ break;
+ }
+ } else { // videoAspectIs4_3
+ switch (afd_mode)
+ {
+ case kAfd_Unset:
+ case kAfd_16_9:
+ case kAfd_16_9_Sp_14_9:
+ break;
+ case kAfd_Same:
+ case kAfd_Sp_4_3:
+ if (AspectIs16_9(displayAspect)) {
+ dispwoff = (dispwoff*3)/4;
+ dispxoff += (dispwoff/6);
+ }
+ break;
+ case kAfd_4_3_Sp_14_9:
+ // this will crop the top and bottom of the
+ // image, and still leave it pillarboxed.
+ if (AspectIs16_9(displayAspect)) {
+ // 7/8 is (9/16) * (14/9)
+ dispyoff -= (disphoff*7)/8;
+ disphoff = (disphoff*9)/14;
+ }
+ break;
+ }
+ }
+ }
if ((fabs(displayAspect - XJ_aspect) / displayAspect) > 0.1){
if(letterbox == kLetterbox_Fill){
if (displayAspect > XJ_aspect)
@@ -1181,3 +1296,10 @@
*/
}
+bool VideoOutput::AspectIs16_9(float aspect) {
+ return (fabs(aspect - 1.777777) < 0.05);
+}
+
+bool VideoOutput::AspectIs4_3(float aspect) {
+ return (fabs(aspect - 1.333333) < 0.05);
+}
Index: libs/libmythtv/videooutbase.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/videooutbase.h,v
retrieving revision 1.51
diff -a -u -b -B -r1.51 videooutbase.h
--- libs/libmythtv/videooutbase.h 26 May 2005 02:17:04 -0000 1.51
+++ libs/libmythtv/videooutbase.h 5 Jun 2005 15:08:52 -0000
@@ -105,9 +105,29 @@
kLetterbox_16_9_Zoom,
kLetterbox_16_9_Stretch,
kLetterbox_Fill,
+ kLetterbox_Afd,
kLetterbox_END
};
+/* Active Format Description(AFD) is set in DVB Streams.
+ * By considering both the aspect ratio and the AFD it
+ * is posible to determine how to present the image in the
+ * correct manner.
+ * See http://www.dtg.org.uk/publications/books/afd.pdf
+ * for the gory details
+ */
+enum AfdMode {
+ kAfd_Unset = 0,
+ kAfd_Same = 8,
+ kAfd_4_3 = 9,
+ kAfd_16_9 = 10,
+ kAfd_14_9 = 11,
+ kAfd_4_3_Sp_14_9 = 13,
+ kAfd_16_9_Sp_14_9 = 14,
+ kAfd_Sp_4_3 = 15,
+ kAfd_END
+};
+
enum FrameScanType {
kScan_Ignore = -1,
kScan_Progressive = 0,
@@ -162,6 +182,8 @@
int GetLetterbox(void) { return letterbox; }
void ToggleLetterbox(int letterboxMode = kLetterbox_Toggle);
+ void SetAfdMode(int afd_mode) { this->afd_mode = afd_mode; };
+
// pass in null to use the pause frame, if it exists.
virtual void ProcessFrame(VideoFrame *frame, OSD *osd,
FilterChain *filterList,
@@ -275,6 +297,9 @@
void AspectSet(float aspect);
+ bool AspectIs16_9(float aspect);
+ bool AspectIs4_3(float aspect);
+
int XJ_width, XJ_height;
float XJ_aspect;
float videoAspect;
@@ -298,6 +323,7 @@
int brightness, contrast, colour, hue;
int letterbox;
+ int afd_mode;
int PIPLocation;
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/globalsettings.cpp,v
retrieving revision 1.254
diff -a -u -b -B -r1.254 globalsettings.cpp
--- programs/mythfrontend/globalsettings.cpp 28 May 2005 00:48:30 -0000 1.254
+++ programs/mythfrontend/globalsettings.cpp 5 Jun 2005 15:08:53 -0000
@@ -1160,12 +1160,14 @@
gc->addSelection(QObject::tr("16/9 Zoom"), "4");
gc->addSelection(QObject::tr("16/9 Stretch"), "5");
gc->addSelection(QObject::tr("Fill"), "6");
+ gc->addSelection(QObject::tr("AFD"), "7");
gc->setHelpText(QObject::tr("This will override any aspect ratio in the "
"recorded stream, the same as pressing the W Key "
"during playback. "
"Fill will \"fill\" the screen with the image clipping as required. "
"Fill is useful when using 4:3 interlaced TV's for display."
- ));
+ "AFD will use the active format descriptor from the stream "
+ "to determine the appropriate display. "));
return gc;
}
More information about the mythtv-dev
mailing list