Das Thema hier ruht zwar schon eine Weile, aber vielleicht kann ja folgende Lösung Einigen helfen. Ich hatte nämlich seit kurzem auch das Problem, daß mein neuer TV seinen Zoom nicht mehr entsprechden dem Bildinhalt automatisch eingestellt hat und somit z.B. auf Pro7, wo ja sehr gern 16:9-Filme aus Spargründen im 4:3-Format ausgestrahlt werden, nun nicht nur links und rechts schwarze Balken zu sehen waren, sondern auch oben und unten. Von der nutzbaren Bildschirmdiagonale blieb da nicht viel übrig. Auch Discovery Channel sendet gern mal 14:9-Inhalte, ohne das WSS-Signal umzustellen. Da gerade Plasma-Fernseher auf immer wiederkehrende schwarze Streifen an den gleichen Stellen über längere Zeit mit Einbrenneffekten reagieren und um in solchen Fällen endlich wieder ein formatfüllendes Bild zu sehen, habe ich mal ein Tool zusammengeschrieben, welches (zumindest schon mal in experimenteller Form) eine dem Bildinhalt entsprechende Umschaltung des WSS-Signals vornimmt. Ich habe es erst mal als eigenständiges Binary realisiert (auch wenn extra Plugins verpönt sind und die bekannten Abschneide-Probleme von Infobar und Senderliste bei aufgezoomtem Bild auftreten), da es sich so leichter bauen und testen läßt. Dieses Tool analysiert nun das innere Drittel (um nicht durch Logos gestört zu werden) des oberen Bildrandes und schaltet entsprechend der Anzahl der gefundenen Schwarzzeilen das WSS zwischen zwei einstellbaren Bildformaten und "aus" um. Im Standardmodus werden wirklich nur schwarze Bildschirmzeilen ausgewertet, im experimentellen Modus wird versucht, z.B. den bei VIVA in diesem Bildbereich gesendeten Schrott zu ignorieren. Als Gerüst für Grabbing und Umwandlung habe ich das Outdoor-Plugin verwendet, welches für diesen Zweck fast ideal war. Das befürchtete Ausbremsen der Box bleibt bei moderater Einstellung des Abfrageintervalls aus und auch eine laufende Aufnahme wird bei aktivem Plugin nicht unterbrochen. Steuerung und Konfiguration erfolgen bei mir über das FlexMenü. Die Config-Datei ist natürlich auch von Hand editierbar. Sinnvollerweise sollte das Teil automatisch mit gestartet werden und ständig laufen, da die Bildinhalte in den Sendern sich ohne weitere Informationen aus dem EPG immer wieder ändern (auch innerhalb einer Sendung).
Hier die (erst mal unkommentierte) Quelle des Tools "aformat.c" an sich:
Code: Alles auswählen
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <dbox/saa7126_core.h>
#define SAA7126_DEVICE "/dev/dbox/saa0"
#include <config.h>
#define P_VERSION "1.1"
#if HAVE_DVB_API_VERSION >= 3
#include <linux/dvb/avia/avia_gt_capture.h>
#else
#include <dbox/avia_gt_capture.h>
#endif
int stride;
static char msg[]="[aformat] ";
static char CFG_FILE[]="/var/tuxbox/config/aformat.conf";
static char ZAP_FILE[]= "/tmp/.actchan";
char *tstr=NULL,*blacklist=NULL, line_buffer[64];
#define XRES 120
#define YRES 65
#define CYRES 32
void TrimString(char *strg)
{
char *pt1=strg, *pt2=strg;
while(*pt2 && *pt2<=' ')
{
++pt2;
}
if(pt1 != pt2)
{
do
{
*pt1=*pt2;
++pt1;
++pt2;
}
while(*pt2);
*pt1=0;
}
while(strlen(strg) && strg[strlen(strg)-1]<=' ')
{
strg[strlen(strg)-1]=0;
}
}
int HTTP_downloadFile(char *host, int port, char *page, char *downloadTarget, int tmo, int repeats)
{
char ustr[256];
sprintf(ustr,"wget -Y off -q -O %s http://%s:%d%s",downloadTarget,host,port,page);
system(ustr);
return 0;
}
int is_blacklisted(void)
{
FILE *fh1;
if(blacklist)
{
if(!HTTP_downloadFile("localhost",80,"/control/zapto", ZAP_FILE, 0, 1))
{
if((fh1=fopen(ZAP_FILE,"r"))!=NULL)
{
while((fgets(line_buffer, sizeof(line_buffer), fh1)>0) && (strlen(line_buffer)<4));
if(strlen(line_buffer)>1)
{
TrimString(line_buffer);
if(strstr(blacklist,line_buffer)!=NULL)
{
fclose(fh1);
return 1;
}
}
fclose(fh1);
}
}
}
return 0;
}
int read_wss(void)
{
int arg=0;
int fd;
if((fd = open(SAA7126_DEVICE,O_RDWR|O_NONBLOCK)) < 0){
perror("SAA DEVICE: ");
return -1;
}
if ( (ioctl(fd,SAAIOGWSS,&arg) < 0)){
perror("IOCTL: ");
close(fd);
return -1;
}
close(fd);
return arg;
}
void write_wss(int mode)
{
int arg=mode;
int fd;
if((fd = open(SAA7126_DEVICE,O_RDWR|O_NONBLOCK)) < 0){
perror("SAA DEVICE: ");
return;
}
if ( (ioctl(fd,SAAIOSWSS,&arg) < 0)){
perror("IOCTL: ");
close(fd);
return;
}
close(fd);
}
inline int compute(int l, int d)
{
switch (d)
{
case 0:
return l;
case 1:
return l+2;
case 2:
return l+8;
case 3:
return 0x1C;
case 4:
return 0x30;
case 5:
return 0x44;
case 6:
return 0x58;
case 7:
return 0x6c;
case 8:
return 0x80;
case 9:
return 0x94;
case 10:
return 0xa8;
case 11:
return 0xbc;
case 12:
return 0xd0;
case 13:
return 0xe4;
case 14:
return l-8;
case 15:
return l-2;
default:
return 0;
}
}
int read_frame(int fd, int experimental)
{
unsigned short buffer[stride*CYRES/2], ts, go, lum=0;
int x, y, tz=3, cnt=0, CXRES=stride/6;
int LXRES=(stride>>1) - CXRES - 4;
read(fd, buffer, stride * CYRES);
for (y=1; y<CYRES && tz; y++)
{
go=1;
for (x=CXRES; x<LXRES && go; x++)
{
if(ts=buffer[y*stride/2+x])
{
if(experimental)
{
int val=buffer[y*stride/2+x];
int dy[2]={val&0xF, (val>>8)&0xF};
lum=compute(lum, dy[1]);
if(abs(lum)>0x02)
go=0;
lum=compute(lum, dy[0]);
if(abs(lum)>0x02)
go=0;
}
else
{
go=0;
}
}
}
if(!go)
tz--;
if(tz)
cnt++;
}
return cnt;
}
int main(int argc, char **argv)
{
int capture, amode=0, tmode, repeat=0, trepeat, fcnt, scnt, tv, loop=3, exp=0, run=0, maxblack14=24, maxblack16=48, wide14=1, wide16=3, normal=0, noswitch=7;
unsigned long towait=3000000L;
long size;
FILE *cfh;
unsigned char *tptr;
printf("aformat: Automatisches Bildschirmformat Version %s\n",P_VERSION);
for(tv=1; tv<argc; tv++)
{
if(strstr(argv[tv],"LOOP")==argv[tv])
run=1;
}
if((cfh=fopen(CFG_FILE,"r"))!=NULL)
{
fseek(cfh, 0, SEEK_END);
size = ftell(cfh);
rewind(cfh);
tstr=malloc(size);
if(fread(tstr, 1, size, cfh))
{
tptr=tstr;
if(((tptr=strstr(tptr,"LOOP=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&loop)!=1)
{
loop=3;
}
}
if(((tptr=strstr(tptr,"REPEAT=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr,"%d",&repeat)!=1)
{
repeat=0;
}
}
if(((tptr=strstr(tptr,"NOSWITCH=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&noswitch)!=1)
{
noswitch=7;
}
}
if(((tptr=strstr(tptr,"MAXBLACK14=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&maxblack14)!=1)
{
maxblack14=24;
}
}
if(((tptr=strstr(tptr,"MAXBLACK16=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&maxblack16)!=1)
{
maxblack16=48;
}
}
if(((tptr=strstr(tptr,"WIDE14=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&wide14)!=1)
{
wide14=1;
}
}
if(((tptr=strstr(tptr,"WIDE16=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&wide16)!=1)
{
wide16=3;
}
}
if(((tptr=strstr(tptr,"NORMAL=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&normal)!=1)
{
normal=0;
}
}
if(((tptr=strstr(tptr,"EXPERIMENTAL=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
if(sscanf(tptr+1,"%d",&exp)!=1)
{
exp=0;
}
}
if(((tptr=strstr(tptr,"BLACKLIST=")!=NULL)&&((tptr=strchr(tptr,'=')!=NULL))
{
blacklist=strdup(tstr);
}
}
fclose(cfh);
}
if(tstr)
free(tstr);
towait=1000000L*loop;
trepeat=repeat;
while(run || (access("/var/etc/.aformat",0)!=-1))
{
amode=read_wss();
if(amode!=noswitch)
{
if(!is_blacklisted())
{
capture=open("/dev/dbox/capture0", O_RDONLY);
capture_stop(capture);
capture_set_input_pos(capture, 0, 0);
capture_set_input_size(capture, 720, 576);
capture_set_output_size(capture, XRES, YRES*2);
stride = capture_start(capture);
usleep(10000);
fcnt=read_frame(capture,exp);
capture_stop(capture);
close(capture);
capture=open("/dev/dbox/capture0", O_RDONLY);
capture_stop(capture);
capture_set_input_pos(capture, 0, 0);
capture_set_input_size(capture, 720, 576);
capture_set_output_size(capture, XRES, YRES*2);
stride = capture_start(capture);
usleep(10000);
scnt=read_frame(capture,exp);
capture_stop(capture);
close(capture);
if((fcnt!=scnt) || (fcnt==31))
{
fcnt=-1;
}
else
{
fcnt-=2;
fcnt<<=3;
}
if(fcnt>=0)
{
tmode=-1;
if(fcnt>=maxblack16)
{
if(amode != 3 && amode != 4 && amode != 5 && amode != 7)
tmode=wide16;
}
else
if(fcnt>=maxblack14)
{
if(amode != 1 && amode != 2 && amode != 6 && amode != 7)
tmode=wide14;
}
else
tmode=normal;
if(tmode>=0 && amode!=tmode)
{
if(!trepeat)
{
write_wss(tmode);
trepeat=repeat;
printf("%sBildformat von Modus %d auf %d umgeschaltet\n",msg,amode,tmode);
}
else
--trepeat;
}
}
else
trepeat=repeat;
}
else
{
if(amode!=8)
write_wss(8);
trepeat=repeat;
}
}
else
trepeat=repeat;
usleep(towait);
}
printf("%sProgrammende\n",msg);
return 1;
}
.. hier die Config "/var/tuxbox/config/aformat.conf":
Code: Alles auswählen
####################################################################################
#### Konfigurationsdatei fuer aformat
#### Automatische Formatanpassung bei Schummelsendern
####################################################################################
# Aller wieviel Sekunden soll getestet werden?
LOOP=3
# Wie oft soll der Test vor dem Umschalten wiederholt werden?
REPEAT=1
# WelcheS Format soll nicht veraendert werden?
NOSWITCH=7
# Ab wieviel schwarzen Zeilen am oberen Bildrand soll auf 14:9 umgeschaltet werden?
MAXBLACK14=16
# Ab wieviel schwarzen Zeilen am oberen Bildrand soll auf 16:9 umgeschaltet werden?
MAXBLACK16=48
# Auf welches Format soll bei 14:9 umgeschaltet werden?
WIDE14=1
# Auf welches Format soll bei 16:9 umgeschaltet werden?
WIDE16=3
# Auf welches Format soll bei erkanntem Vollbild umgeschaltet werden?
NORMAL=0
# Soll der experimentelle Modus verwendet werden?
EXPERIMENTAL=1
# moegliche Formate (siehe Kommando "saa")
# 0 4:3 full format
# 1 14:9 center letterbox
# 2 14:9 top letterbox
# 3 16:9 center letterbox
# 4 16:9 top letterbox
# 5 >16:9 center letterbox
# 6 4:3 with 14:9 center letterbox
# 7 16:9 full format (anamorphic)
# 8 turned off
# Auf welchen Kanaelen soll keine Formatumschaltung erfolgen?
BLACKLIST=
... und hier die readme.txt dazu:
####################################################################################
#### aformat 1.1
#### Automatische Formatanpassung bei Schummelsendern
####################################################################################
Viele Sender (z.B. "Discovery-Channel" oder "Discovery Geschichte") machen es sich aus
Kostengründen zur Angewohnheit, auch Sendungen, welche ursprünglich im 16:9- oder sogar
Kino-Format aufgenommen wurden, einfach auf 4:3 runterzuskalieren und dann so zu senden.
Das Ergebnis besteht dann bei 16:9-Fernsehern in schwarzen Streifen nicht nur links und
rechts sondern zusätzlich oben und unten. Da ist dann auf dem nutzbaren Bereich eines
Fernsehers nicht mehr viel zu sehen. Auch mögen Plasmafernseher solche Balken im Hinblick
auf den Einbrenneffekt überhaupt nicht.
Deshalb habe ich mal eine Testversion einer entsprechenden Umschaltung gebaut. Sie wertet
die Größe der schwarzen Balken am oberen Bildrand aus und zoomt das Bild entsrechend der
gemachten Einstellungen auf. Das funktioniert allerdings nur bei Fernsehern, welche das WSS-
Signal (wide screen signaling) auswerten können. Das sollten die meisten können.
Für die Basisfunktion ist das Plugin "aformat" mit den Rechten 755 nach /var/plugins/ und
"aformat.conf" nach /var/tuxbox/config/ zu kopieren. Gestartet wird entweder automatisch
oder über das Flexmenü.
Wichtig: Um das Plugin beim Boxenstart automatisch zu starten, ist noch die Zeile
"[ -e /var/etc/.aformat ] && ( sleep 20; aformat ) &" in die start_neutrino vor dem eigent-
lichen Start von Neutrino einzufügen.
Start und Konfiguration über das Flexmenü:
Installation des Flexmenüstarts:
--------------------------------
plrun_aformat.mnu --> nach /var/tuxbox/config/flexinc/
in_plugin_run.mnu_einfuegen --> den Inhalt in /var/tuxbox/config/flexinc/plugin_run.mnu einfügen
Gesteuert wird das Plugin nun übers Menü unter:
Automatikformat starten / beenden
Installation der Menükonfiguration:
-----------------------------------
afops --> nach /var/plugins/ + Dateirechte 755
plconfig_aformat.mnu --> nach /var/tuxbox/config/flexinc
in_plugin_config.mnu_einfuegen --> den Inhalt in /var/tuxbox/config/flexinc/plugin_config.mnu einfügen
Ich habe das gesamte Paket
hier hochgeladen. Es enhält neben der Binary auch die passenden Einträge für das FlexMenü und ein zugeschnittenes Konfigurationsscript. Wer das FlexMenü nicht verwendet, kann den folgenden Abschnitt überspringen. Zum Verständnis der Dateien muß ich mal kurz auf das hier verwendete Konzept des FlexMenüs eingehen. Um nicht immer bei jeder kleinen Änderung, Installation oder Deinstallation die zentrale Konfigurationsdatei des FlexMenüs bearbeiten zu müssen, hat sich folgendes Konzept eingebürgert: Jedes Plugin hat eine eigene FlexMenü-Konfig für den Start und eine für die Konfiguration. Diese pluginspezifischen Konfigs werden mittels INCLUDE in zentrale Start- und Konfigurationsdateien eingebunden, welche wiederum in der zentralen Menüdatei "shellexec.conf" includiert sind. Somit muß bei einer Änderung nur die kleine pluginspezifische Konfig-Datei bearbeitet werden und beim Installieren bzw. Deistallieren des Plugins werden einfach die entsprechenden INCLUDE-Zeilen in den Zentraldateien hinzugefügt oder halt gelöscht. Es existiert also die zentrale shellexec.conf in /var/tuxbox/config/, welche mittels
Code: Alles auswählen
INCLUDE=/var/tuxbox/config/flexinc/plugin_run.mnu
INCLUDE=/var/tuxbox/config/flexinc/plugin_config.mnu
die Zentraldateien einbindet. Diese enthalten (neben den Einträgen für die übrigen Plugins) auch die Verweise auf die Menüdateien des Autoformats:
/var/tuxbox/config/flexinc/plugin_run.mnu:
/var/tuxbox/config/flexinc/plugin_config.mnu:
Code: Alles auswählen
INCLUDE=/var/tuxbox/config/flexinc/plconfig_aformat.mnu
Wer will, kann diese beiden Dateien auch gleich direkt in die shellexec.conf einbinden. Das Konfigurations-Script geht allerdings davon aus, daß daß die beiden Menüdateien in var/tuxbox/config/flexinc/ liegen und auch wie angegeben heißen. Wer das ändern will, muß das Script entsprechend anpassen.
Um das Plugin automatisch starten zu können, ist der Eintrag
in die start_neutrino vor der Keep-Alive-Schleife von Neutrino einzufügen. Wer den Eintrag lieber in der init.end vornehmen möchte, muß aformat dann aber innerhalb der Keep-Alive-Schleife in der start_neutrino hinter dem Aufruf von Neutrino killen.
Für die Anpassung der Einstellungen in der aformat.conf per Hand sind die entprechenden Parameter in der Config selbst und in der readme.txt erläutert.
Als kleine Einstellungshilfe hier mal die ganzen Settings, mit welchen ich mit meinem Panasonic TX-P37X10E immer das passende Format ohne Eierköpfe oder abgeschnittene Bildbereiche habe:
Code: Alles auswählen
Plugin-Settings: Default-Einstellungen
DBox: Einstellungen -> Video -> Bildschirmformat: automatisch
Fernseher: Aspect 4:3
Zusammenfassend kann ich sagen, daß mit den passenden Einstellungen außer bei Animationsfilmen (vor allem bei den Simpsons) eine doch recht zuverlässige Erkennung von Letterbox-Sendungen und die entsprechende Umschaltung erfolgt, ohne die Box zu sehr zu belasten. An Verbesserungsvorschlägen bin ich natürlich interessiert. Vielleicht findet ja jemand noch eine sicherere Auswertemethode oder baut es gleich in Neutrino ein. Wobei im Hinblick auf Updates wohl erst mal die Plugin-Version günstiger ist.
PS: Ich hoffe, ich habe alle anstößigen Hinweise aus den Dateien entfernt und dabei keine zusätzlichen Feher eingebaut. Falls nicht, bitte nicht zerfleischen sondern sachlich darauf hinweisen.