Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

transformer timecode en chiffre hexa

10 réponses
Avatar
barrack
je cherche =E0 transformer un timecode exprim=E9 en seconde en long dont
la repr=E9sentation prendrait cette forme :

j'ai un nombre en seconde de cette forme :
unsigned long tcinsecs =3D 3600,00secondes
qui represente 01H00M00S00f

en unsigned long timecode =3D 0x01000000

j'ai donc le code suivant =3D

timecode=3D ((tcinsecs/3600 << 24) |
(tcinsecs/60%60 <<16) |
(tcinsecs%60<<8)|
nbframes)

mais pour des valeurs comme 02H34M21S05f
j'ai comme resultat :
0x022E2105
au lieu de
0x02342105

et je ne comprends pas pourquoi.

merci pour votre aide

10 réponses

Avatar
Emmanuel Delahaye
je cherche à transformer un timecode exprimé en seconde en long dont
la représentation prendrait cette forme :

j'ai un nombre en seconde de cette forme :
unsigned long tcinsecs = 3600,00secondes


Je ne vois pas comment un entier pourrait représenter un nombre décimal.

unsigned long tcinsecs = 3600; /* secondes */

qui represente 01H00M00S00f

en unsigned long timecode = 0x01000000


unsigned long timecode = 0x01000000;

Si j'ai bien compris, tu veux un unsigned long structuré comme suit :

31-24 23-16 15-8 7-0
H M S CS

Alors il y a un problème de conception. Si le timecode est en
centisecondes (je suppose que le champ f a une plage de 00 à 99
centisecondes), l'entier qui le représente doit être de la même unité.

unsigned long tcincentisecs = 360000; /* centisecondes */

--
A+

Emmanuel Delahaye

Avatar
Emmanuel Delahaye

Il ce peut que ce que j'appelle le champ 'centisecondes' soit en fait le
champ 'frames'

#include <stdio.h>

unsigned long tc2cs(char const *tc, int *perr)
{
unsigned long centisec = 0;
int err = 1;
unsigned h;
unsigned m;
unsigned s;
unsigned cs; /* centisecond */
int n = sscanf(tc, "%uH%uM%uS%uf", &h, &m, &s, &cs);

if (n == 4)
{
centisec = h * 3600 * 100
+ m * 60 * 100
+ s * 100
+ cs ;
err = 0;
}

if (perr != NULL)
{
*perr = err;
}

return centisec;
}

unsigned long cs2hex(unsigned long cs)
{
unsigned long hex = (cs / (3600 * 100)) << 24
| (cs / (60 * 100) % 60) << 16
| ((cs / 100) % 60) << 8
| cs % 100
;
return hex;
}

int main(void)
{
char const s[] = "02H34M21S05f";
int err;
unsigned long cs = tc2cs(s, &err);

if (!err)
{
printf ("'%s' = %lun", s, cs);

{
unsigned long hex = cs2hex(cs);

printf ("hex = %08lXn", hex);
}
}
else
{
printf ("format error in '%s'n", s);
}
return 0;
}

'02H34M21S05f' = 926105
hex = 02221505

Mais il serait plus simple et plus rapide de convertir directement la
chaine en unsigned long structuré.

#include <stdio.h>

unsigned long tc2hex(char const *tc, int *perr)
{
unsigned long hex = 0;
int err = 1;
unsigned h;
unsigned m;
unsigned s;
unsigned f; /* frames */
int n = sscanf(tc, "%uH%uM%uS%uf", &h, &m, &s, &f);

if (n == 4)
{
hex = h << 24
| m << 16
| s << 8
| f << 0;
err = 0;
}

if (perr != NULL)
{
*perr = err;
}

return hex;
}

int main(void)
{
char const s[] = "02H34M21S05f";
int err;
unsigned long hex = tc2hex(s, &err);

if (!err)
{
printf ("'%s' = %08lXn", s, hex);

}
else
{
printf ("format error in '%s'n", s);
}
return 0;
}

--
A+

Emmanuel Delahaye
Avatar
Emmanuel Delahaye

Il se peut que ce que j'appelle le champ 'centisecondes' soit en fait le
champ 'frames'

#include <stdio.h>

unsigned long tc2cs(char const *tc, int *perr)
{
unsigned long centisec = 0;
int err = 1;
unsigned h;
unsigned m;
unsigned s;
unsigned cs; /* centisecond */
int n = sscanf(tc, "%uH%uM%uS%uf", &h, &m, &s, &cs);

if (n == 4)
{
centisec = h * 3600 * 100
+ m * 60 * 100
+ s * 100
+ cs ;
err = 0;
}

if (perr != NULL)
{
*perr = err;
}

return centisec;
}

unsigned long cs2hex(unsigned long cs)
{
unsigned long hex = (cs / (3600 * 100)) << 24
| (cs / (60 * 100) % 60) << 16
| ((cs / 100) % 60) << 8
| cs % 100
;
return hex;
}

int main(void)
{
char const s[] = "02H34M21S05f";
int err;
unsigned long cs = tc2cs(s, &err);

if (!err)
{
printf ("'%s' = %lun", s, cs);

{
unsigned long hex = cs2hex(cs);

printf ("hex = %08lXn", hex);
}
}
else
{
printf ("format error in '%s'n", s);
}
return 0;
}

'02H34M21S05f' = 926105
hex = 02221505

Mais il serait plus simple et plus rapide de convertir directement la
chaine en unsigned long structuré.

#include <stdio.h>

unsigned long tc2hex(char const *tc, int *perr)
{
unsigned long hex = 0;
int err = 1;
unsigned h;
unsigned m;
unsigned s;
unsigned f; /* frames */
int n = sscanf(tc, "%uH%uM%uS%uf", &h, &m, &s, &f);

if (n == 4)
{
hex = h << 24
| m << 16
| s << 8
| f << 0;
err = 0;
}

if (perr != NULL)
{
*perr = err;
}

return hex;
}

int main(void)
{
char const s[] = "02H34M21S05f";
int err;
unsigned long hex = tc2hex(s, &err);

if (!err)
{
printf ("'%s' = %08lXn", s, hex);

}
else
{
printf ("format error in '%s'n", s);
}
return 0;
}

--
A+

Emmanuel Delahaye
Avatar
Pierre Maurette

Il se peut que ce que j'appelle le champ 'centisecondes' soit en fait le
champ 'frames'
Oui. C'est le champ 'images'. Il boucle modulo 24 (cinéma), 25 (télé

50Hz), 30 (télé 60Hz). C'est même pour le dernier en télé couleur du
"30 drop frame", en moyenne du 29,97.
Il existe une normalisation (SMTPE, EBU) de ce code sur 80 bits.

--
Pierre Maurette

Avatar
barrack
oui, c'est un entier, pas un flottant,

et le nombre de frames qui reste est calculé par ailleurs avec le
framerate
Avatar
Antoine Leca
En news:,
barrack va escriure:
mais pour des valeurs comme 02H34M21S05f
j'ai comme resultat :
0x022E2105
au lieu de
0x02342105


Quel est le problème ?

Tu veux voir les chiffres base 10 ? Genre 0x02342105 ? il faut alors
utiliser le "binary coded decimal" (BCD, déja utilisé à Babylone au IIIe
millénaire), donc convertir une valeur entre 0 et 59 en deux quantités
(dizaines et unités), et encoder chacun de ces deux chiffres comme chiffre
hexadécimal avec << N, N multiple de 4.

Tu veux avoir les quantités dans chaque octet ? Genre 0x02221505 ? Ton code
a l'air correct pour cela...

Si j'étais toi, avec les valeurs que tu nous as passées, je reverrai le code
qui transforme tcinsecs en 02H34M21S05f (ou le contraire)...


Antoine

Avatar
Ludovic Bostral
--
"Antoine Leca" a écrit dans le message de news:
e1d87q$ipp$
En news:,
barrack va escriure:
mais pour des valeurs comme 02H34M21S05f
j'ai comme resultat :
0x022E2105
au lieu de
0x02342105


Quel est le problème ?

Tu veux voir les chiffres base 10 ? Genre 0x02342105 ? il faut alors
utiliser le "binary coded decimal" (BCD, déja utilisé à Babylone au IIIe
millénaire), donc convertir une valeur entre 0 et 59 en deux quantités
(dizaines et unités), et encoder chacun de ces deux chiffres comme chiffre
hexadécimal avec << N, N multiple de 4.

C'est exactement ce que je veux faire,

Je vais voir ce qu'est le BCD,
Mais si tu peux m'en dire plus ca m'interesse...

Ludovic


Avatar
Pierre Maurette
En news:,
barrack va escriure:
mais pour des valeurs comme 02H34M21S05f
j'ai comme resultat :
0x022E2105
au lieu de
0x02342105


Quel est le problème ?

Tu veux voir les chiffres base 10 ? Genre 0x02342105 ? il faut alors
utiliser le "binary coded decimal" (BCD, déja utilisé à Babylone au IIIe
millénaire), donc convertir une valeur entre 0 et 59 en deux quantités
(dizaines et unités), et encoder chacun de ces deux chiffres comme chiffre
hexadécimal avec << N, N multiple de 4.

Tu veux avoir les quantités dans chaque octet ? Genre 0x02221505 ? Ton code
a l'air correct pour cela...

Si j'étais toi, avec les valeurs que tu nous as passées, je reverrai le code
qui transforme tcinsecs en 02H34M21S05f (ou le contraire)...
Je ne sais plus qui est l'OP dans ce fil ;-) je réponds donc ici.


Je trouve que ni le départ ni même la fin ne sont très clairs. D'où
viennent les données et sous quelle forme ? De mes souvenirs, ça peut
être d'un port RS422, d'une EDL (edit list), etc.
Y a-t-il un souci possible de boutisme ?
Pour la conversion, on peut peut-être prendre:

#include <stdio.h>

typedef unsigned char byte_t;

#define CONV_ERROR 0xFF

byte_t ByteToBCD(byte_t byte)
{
return (byte>99)?
CONV_ERROR:
((byte/10)<<4)|(byte%10)
;
}

int main(void)
{
byte_t test = 24;
printf("%d 0x%X 0x%Xn", test, test, ByteToBCD(test));
return 0;
}


Le code du message original (que je ne comprends pas entièrement)
deviendrait:

timecode = ByteToBCD(tcinsecs/3600 << 24) |
ByteToBCD(tcinsecs/60%60 <<16) |
ByteToBCD(tcinsecs%60<<8)|
ByteToBCD(nbframes)
;

Mais je ne suis pas certain qu'il soit efficace d'utiliser du BCD
"compressé", à deux digits par octet. Peut-être extraire les valeurs et
fabriquer une chaîne decaractères ?

--
Pierre Maurette


Avatar
Ludovic Bostral
--
---------
Ludovic Bostral
"Pierre Maurette" a écrit dans le message de
news:
En news:,
barrack va escriure:
mais pour des valeurs comme 02H34M21S05f
j'ai comme resultat :
0x022E2105
au lieu de
0x02342105


Quel est le problème ?

Tu veux voir les chiffres base 10 ? Genre 0x02342105 ? il faut alors
utiliser le "binary coded decimal" (BCD, déja utilisé à Babylone au IIIe
millénaire), donc convertir une valeur entre 0 et 59 en deux quantités
(dizaines et unités), et encoder chacun de ces deux chiffres comme
chiffre
hexadécimal avec << N, N multiple de 4.

Tu veux avoir les quantités dans chaque octet ? Genre 0x02221505 ? Ton
code
a l'air correct pour cela...

Si j'étais toi, avec les valeurs que tu nous as passées, je reverrai le
code
qui transforme tcinsecs en 02H34M21S05f (ou le contraire)...
Je ne sais plus qui est l'OP dans ce fil ;-) je réponds donc ici.




C'est moi :)

Je trouve que ni le départ ni même la fin ne sont très clairs. D'où
viennent les données et sous quelle forme ? De mes souvenirs, ça peut être
d'un port RS422, d'une EDL (edit list), etc.
Y a-t-il un souci possible de boutisme ?
Pour la conversion, on peut peut-être prendre:

#include <stdio.h>

typedef unsigned char byte_t;

#define CONV_ERROR 0xFF

byte_t ByteToBCD(byte_t byte)
{
return (byte>99)?
CONV_ERROR:
((byte/10)<<4)|(byte%10)
;
}

int main(void)
{
byte_t test = 24;
printf("%d 0x%X 0x%Xn", test, test, ByteToBCD(test));
return 0;
}


Le code du message original (que je ne comprends pas entièrement)
deviendrait:

timecode = ByteToBCD(tcinsecs/3600 << 24) |
ByteToBCD(tcinsecs/60%60 <<16) |
ByteToBCD(tcinsecs%60<<8)|
ByteToBCD(nbframes)
;




votre code m'a mis sur la voie :

En fait ce que je veux c'est bien ce que décrit Antoine Lecca dans son
premier point,
Mais il faut que je décale le resultat de ByteToBCD :
timecode = ByteToBCD(tcinsecs/3600) << 24 |
ByteToBCD(tcinsecs/60%60) <<16 |
ByteToBCD(tcinsecs%60)<<8|
ByteToBCD(nbframes)
;

Et là j'ai semble-t-il ce que je veux.

L'objectif est d'ajouter des informations de type SMPTE dans une video.

Merci à vous,
Ludovic



Avatar
Pierre Maurette
[...]
Le code du message original (que je ne comprends pas entièrement)
deviendrait:

timecode = ByteToBCD(tcinsecs/3600 << 24) |
ByteToBCD(tcinsecs/60%60 <<16) |
ByteToBCD(tcinsecs%60<<8)|
ByteToBCD(nbframes)
;




votre code m'a mis sur la voie :

En fait ce que je veux c'est bien ce que décrit Antoine Lecca dans son
premier point,
Mais il faut que je décale le resultat de ByteToBCD :
timecode = ByteToBCD(tcinsecs/3600) << 24 |
ByteToBCD(tcinsecs/60%60) <<16 |
ByteToBCD(tcinsecs%60)<<8|
ByteToBCD(nbframes)
;
Ooooops ! Bien sûr ....


--
Pierre Maurette