Jump to content

fredericopissarra

Membros
  • Content Count

    267
  • Joined

  • Last visited

Everything posted by fredericopissarra

  1. PS: Se o aspecto é próximo do desejado e reescalonar causará distorções, use o macete das barras pretas!
  2. Tenho observado que a maioria dos vídeos que baixamos, seja via torrents, seja via outros sites de vídeo (Youtube, e... a-ham... XVideos, PornHub, etc...), não aderem aos padrões de vídeos... Por exemplo, O frame-rate pode ser não padronizado (geralmente, 24 fps [filmes da telona], 24000/1001 fps ou 23.976 fps [filmes da telona no padrão NTSC], 25 fps [PAL]; ou 30000/1001 ou 29.97 fps [NTSC]). Alguns frame-rates não são padrão, como 30 fps, por exemplo... Existe um outro problema relativo aos frame-rates: Num container de vídeo são armazenados 2 frame-rates: O do qual o vídeo foi codificado e o qual o vídeo será "tocado". Às vezes os dois não batem... Seria prudente que a relação entre eles fosse 1:1, da mesma forma que a resolução gráfica para o aspect ratio. Outro problema é o aspect ratio. Os mais comuns são 4/3 (letter-box) e 16/9 (wide-screen), mas existem outros: 3/2 (35mm still camera film), 16/10 (outro padrão para wide-screen, menos usual), 5:3 (Super 16 - padrão Europeu), 64/24 e 32:9 (ultra wide-screen - também neos usual). No entanto, muitos vídeos usam resoluções gráficas não padronizadas, distorcendo a imagem (daí o macete das barras pretas que mostrei antes)... Um terceiro problema, mas que não entra, necessariamente, na categoria de padrões, é o bitrate em que o vídeo é codificado... É comum, hoje em dia, que vídeos tenham bitrates MUITO altos, na tentativa de compensar distorções causadas por "artefatos" no vídeo. Então, é comum ver vídeos HD (720p), por exemplo, com bitrates na ordem de 4~5 Mb/s, quando, aproximadamente 2 Mb/s é mais que suficiente. Isso diminuirá o tamanho do vídeo com perdas insignificantes. Minha dica, use o ffmpeg para converter seus vídeos para os padrões... Por exemplo, se você tem um vídeo em 640x382 (uma resolução não padrõnizada - aspecto 320/191), note que ele está mais próximo do aspecto 16/9 (wide screen) do que 4/3 (letter-box). Assim, convertê-lo para 16/9 pode ser uma boa ideia... Ainda, ajuste o framerate... suponha que o vídeo original use 30 fps, usar NTSC pode ser outra boa ideia... E, como vamos usar widescreen, a resolução final poderá ser 1280x720 (duplicar x e y não causará problemas de distorção, se o filtro certo for usado)... assim, com uma nVidia, podemos fazer: $ ffmpeg -hwaccel cuvid \ -i videoin.mp4 \ -c:v h264_nvenc \ -pix_fmt yuv420p \ -bufsize 1.998M -maxrate 1.998M -b:v 1.998M \ -r ntsc \ -vf scale=1280:720:flags=lanczos,setdar=16/9 \ -c:a ac3 \ -b:a 128k -ac 2 -ar 44.1k -async 1 \ videoout.mp4 Aqui ajusto chroma subsampling para o YUV 4:2:0 (algumas vezes o vídeo vêm codificado com NV12, por exemplo); o bitrate para 1.998 Mb/s (segundo aquela minha "fórmula mágica" num post anterior); o frame-rate para 29.97 (ntsc), reescalono o vídeo para 1280x720, usando o filtro lanczos, ajusto o aspect ratio (DAR) para 16/9 [o ffmpeg fará isso sozinho, mas prefiro dar uma mão])... Logo depois uso o codec AC-3 (AAC não funciona na minha TV! hehe), ajustando o bitrate do audio para 128 kb/s, stereo com sampling-rate de 44.1 kHz (48 kHz é exagero!). No audio, o filtro -async 1 (alias para um filtro aresample) garante que o audio estará sincronizado com o novo frame-rate do vídeo... Há uma desvantagem em fazer isso se seu container tem um stream de legenda (subtitle) emburido... As legendas estão sincronizadas com o frame-rate do vídeo, ao mudar o frame-rate não temos como sincronizar as legendas via algum filtro... Assim, retire a legenda do vídeo (opção -sn), obtenha a legenda e resincronize-a usando algum outro software (SubRip, por exemplo). Voilà! videoout.mp4 está dentro do padrão para widescreen 720p. Se você tem um PC com video on-board, mas seu processador é Intel i# de uma geração mais recente (6ª geração em diante?), pode trocar a opção -hwaccel cuvid por: "-hwaccel vaapi -vaapi_device /dev/dri/renderD128"; trocar o encoder para "h264_vaapi", mas deve adicionar o filtro "hwupload" na opção -vf e pode até mudar o escalonador para "scale_vaapi": "-vf hwupload,scale_vaapi=1280:720,setdar=16/9" (para gerações anteriores a 6ª, deixe com "scale=1280:720:flags=lanczos,hwupload,setdar=16/9".
  3. Existem diferenças óbvias entre "dúvida" e "ignorância" (no sentido estrito da palavra). Não saber alguma coisa não é uma "dúvida"... Recomendo que procure material para estudo e estude... Eis alguns pontos: Não existe linguagem "ASSEMBLER"... Assembler é o nome dado ao compilador da linguagem "Assembly" (com 'y'). Vem do inglês, "montador"; Não existe UMA linguagem assembly: Cada família de processadores tem a sua... Intel/AMD x86 é diferente dos ARM, que é diferente dos Risc-V, que é diferente dos MIPS, PowerPC, etc...; Existem vários "sabores" de ASSEMBLERs (montadores); Existem vários modos de operação nos x86-64... Um programa feito para DOS não funciona no Windows e vice-versa (especialmente no Win10); Um "hello world" em assembly dependerá do sistema operacional em uso e do modo de operação... Assembly não é, por definição, portável.
  4. Cruz credo... compra um processador decente, misifio...
  5. Em primeiro lugar, a explicação que dei acima está bem longe de ser um código compilável (são fragmentos). Em segundo... o que diabos é uma "CPU ADM"?
  6. Ahhhh... mas um char não tem sempre 8 bits de tamanho? Nope! Em arquiteturas antigas 1 byte era de 9 bits e existem arquiteturas que não conseguem lidar com 1 byte isolado, dai char pode ter mais que 8 bits...
  7. Uma dica que me repassaram agorinha... Sempre achei que CHAR_BITS, definido em limits.h, fosse o tamanho em bits do tipo char. De fato é, mas também é o tamanho em bits de um byte. A sessão 6.2.6.1 §4 da ISO 9989 (1999 em diante, pelo menos) é clara ao dizer que todos os objetos que não são bit-fields têm tamanho n * CHAR_BITS, onde n é o tamanho em bytes devolvido pelo sizeof. Fica a dica.
  8. Depende do que você interpreta por "variável". Um valor numérico pode ser armazenado na memória ou num registrador... Ela pode ser inteira ou ponto flutuante... Para mostrar, na sintaxe do NASM, eis alguns exemplos: section .data ; define uma região de 4 bytes no segmento de dados contendo o valor 0x0000000A (10), nomeado 'myvar' myvar: dd 10 Daqui para frente, a referência à memória é feita através desse "identificador" 'myvar'. Por exemplo: mov eax,[myvar] ; Lê 4 bytes da memória, na posição de 'myvar', no segmento de dados, e coloca em EAX. Note que poderíamos colocar o valor 10 diretamente em EAX e, nesse caso, o registrador EAX seria sua "variável": mov eax,10 No caso do NASM, valores numéricos em ponto flutuante podem ser atribuídos da mesma forma, na memória: section .data myvar2: dd 3.141592 Esse 'myvar2' é um float, ocupando 4 bytes, da mesma forma que um 'int', no exemplo anterior. E, assim como no exemplo anterior, ele pode ser acessado por uma instrução, mas o 'registrador' será diferente... Por exemplo, via SSE: movss xmm0,[myvar2] Outro lugar onde suas varíaveis podem ser colocadas é na pilha. É o caso de variáveis 'locais'. Mas, isso exige alguma manipulação do "apontador de pilha" (ESP ou RSP, dependendo do modo de operação). Por exemplo: sub rsp,8 ; reserva espaço na pilha (precisa estar alinhada de 8 em 8 bytes!). mov dword [rsp],10 ; escreve 10 na pilha. ... add rsp,8 ; recupera o espaço reservado anteriormente... Bons compiladores de alto nível (C, por exemplo) tentam manter as variáveis locais em registradores sempre que podem para evitar esse tipo de manipulação da pilha (e gastar menos espaço na memória, ganhando velocidade de processamento também).
  9. O código de exemplo do PRNG "bixado", no post, tinha um errinho na geração do arquivo gráfico PPM. Corrigi. É bom lembrar que estou enviando o arquivo para stdout ao invés de gravá-lo diretamente num arquivo, assim, a chamada do executável (como está no post) deve ser: $ cc -O2 -o random random.c $ ./random > pic.ppm Use o 'eog' ("Eye of GNOME", acho, ou "GNOME Image Viewer") para ver o arquivo ou o converta para PNG com o ImageMagick: $ convert pic.ppm pic.png []s Fred
  10. Acredito que eu ainda não tenha mostrado esse post aqui: https://is.gd/AtpHNC Fica a dica de um teste visual para Pseudo Random Numbers Generators. Outra dica (que não está no post) é o uso do utilitário dieharder (disponível nos Linux) para análises de RNGs. []s Fred
  11. Considerações sobre aspect rations comuns. São 2: WideScreen (16/9) e LetterBox (4:3). O segundo é o aspecto das antigas TVs com CRTs. Uma resolução de 640x480 tem aspecto 4:3, por exemplo. Se formos fazer padding sempre para Widescreen isso tem que ser levado em consideração: No caso de um vídeo widescreen, mas com aspecto diferente de 16:9 (resolução não padrão), barras horizontais devem ser colocadas. Mas, note que elas não consumirão muito do espaço útil da tela (a não ser que a resolução vertical seja mesmo pequena). O escalonamento do vídeo original deve ser feito de forma que o width seja o mesmo do espaço do padding... No caso do formato letterbox (4:3), barras verticais devem ser adicionadas (a centralização do vídeo será feita horizontalmente e o vídeo original deve ser escalonado para fazer com que height seja o mesmo do espaço do padding)... Mas, note que muito do espaço útil é perdido:
  12. Existia um erro no texto com relação ao uso dos filtros scale e pad, em sequência... Corrigi o texto... O problema era que as pseudo-variáveis ih e iw do filtro pad levam em consideração a altura e comprimento, respectivamente, do vídeo de entrada (não do vídeo escalonado - ao que parece)... daí, substituí pelos valores fixos ao invés de usar as variáveis.
  13. Tenho uma antiga TV Sony Bravia de 42"... Tive certos problemas com ela em relação à vídeos que posso "tocar", via pendrive: Se o vídeo têm um bitrate muito alto, nada feito; Se o vídeo não estiver nos containers MPEG-1, MPEG-2, MPEG-4 ou WMV, nada feito; Se o vídeo estiver num aspect ratio diferente de 16/9, a imagem distorce. O último parece ser verdadeiro para todas as TVs em que testei o player de vídeo embutido nelas. Aparentemente o SAR (source aspect ratio) e DAR (display aspect ratio) não são respeitados se o DAR não for 16/9 ou 4/3. ffmpeg ao resgate: Bem... eis a linha de comando para conversão de um vídeo qualquer para um formato que pode ser "universal" para todas as TVs e, ainda assim, criar o menor arquivo possível, sem perda de qualidade significativa... O primeiro passo é calcular o bitrate correto para o vídeo. Isso pode ser feito com a seguinte equação: Como exemplo, para um vídeo em 1280x720 @ 29.97 fps, o bitrate ficará em 1.998 Mb/s. O outro passo é determinar a resolução do vídeo original. Podemos usar o próprio ffmpeg para isso, mas prefiro usar o mediainfo: $ mediainfo --inform='Video;%Width%' videoin.mp4 $ mediainfo --inform='Video;%Height%' videoin.mp4 Se, escalonando o vídeo obtivermos o tamanho vertical menor que a resolução máxima vertical, estamos no caminho certo. Por exemplo... suponha que tenhamos um vídeo com uma resolução maluca como 1316x638. Se quisermos, aqui, uma resolução HD (1280x720) o vídeo terá que ser escalonado para 1280x620: $ bc <<< 'scale=3; 1280/(1316/638)' 620.756 Como o valor é par, ignoramos a parte fracionária... Agora, estamos prontos para recodificar o vídeo: $ ffmpeg -hwaccel cuvid -i videoin.mp4 \ -c:v h264_nvenc -r ntsc \ -maxrate 1.998M -bufsize 1.998M -b:v 1.998M \ -vf 'scale=1280:620:flags=lanczos,pad=1280:720:0:(720-620)/2:black,setdar=16/9' \ -c:a ac3 -b:a 128k -ac 2 -ar 44.1k -async 1 \ videoout.mp4 Aqui uso os CUDA cores da placa de vídeo nVidia para decodificar os frames (-hwaccel cuvid) e o encoder da placa de vídeo para recodificá-los (-c:v h264_nvenc). Ajusto o bitrate fixo (constant bitrate) para 1.998 Mb/s, ajusto o framerate para o padrão NTSC (30000/1001 fps). Uso o filtro de escalonamento dos frames para ajustar a resolução que quero (1280x620), usando o método 'lanczos' de extrapolação para minimizar os artefatos que podem surgir no escalonamento e depois uso o filtro 'pad' para preencher o espaço de 100 pixels com um fundo preto, colocando a imagem exatamente no meio desse grande quadro de 1280x720... Por fim, ajusto os aspect ratios SAR e DAR, ajustanto o DAR para 16/9. Você pode deixar que o próprio ffmpeg calcule o escalonamento vertical modificando o filtro scale para 'scale=1280:-1:flags=lanczos', mas se o tamanho vertical for ímpar o ffmpeg pode reclamar. Prefiro eu mesmo ajustar o valor desejado, mesmo porque ele será usado no filtro pad... Só tenha certeza que o tamanho vertical será menor ou igual a 720 (no caso da resolução 1280x720)... No que tange o áudio, minha TV não suporta AAC, então uso AC3 e acho o bitrate de 128 kb/s suficiente, mas converto o sampling rate para 44.1 kHz para diminuir o stream de áudio, bem como garanto que a saída seja 'stereo' (-ac 2)... Como estou modificando o framerate do vídeo, aplico também o filtro de áudio de sincronização a cada 1 segundo (-async 1). O arquivo videoout.mp4 conterá o vídeo no container MPEG-4 (o ffmpeg pega pela extensão), usando codecs h264 e ac3 e estará na resolução 1280x720 com DAR setado em 16/9... Vídeo "pequeno" (com essa técnica consigo um vídeo com tamanho de 28% do vídeo original, dependendo do caso), que tocará sem distorções e excelente qualidade. Se você gosta de assistir vídeos em FullHD (1920x1080), basta modificar os cálculos de acordo. PS: Se você não tem uma placa nVidia pode tentar usar um decoder VAAPI (Intel) ou não usar a aceleração (retire o -hwaccel cuvid, acima)... Ainda, terá que modificar o encoder para 'libx264', ao invés de 'h264_nvenc'.
  14. Foi corrigido um bug histórico do T50 no cálculo do campo doff (data offset no 4º dword do datagrama). Fui chamado a atenção para esse bug pelo usuário do gitlab Nik que me apontou que era desnecessária a manipulação de endianess, no caso desse campo. Corrigido agora na versão 5.8.7, disponível tanto no gitlab quanto no sourceforge: https://gitlab.com/fredericopissarra/t50 https://t50.sf.net/ []s Fred PS: O último commit, depois da tag v5.8.7 contém alguns 'helper scripts' simples que uso para criar a distribuição (arquivo tar.gz e assinatura). PS2: Sem querer, estraguei a versão 5.8.5 no sourceforge. Ela foi deletada. Se for obter o bicho, obtenha a última versão (5.8.7).
  15. Apenas uma nota histórica: Em 1968 Dijkstra (um famoso professor universitário) publicou um artigo dizendo que 'goto' é ruim. De lá para cá os cursos universitários adotaram essa opinião como mantra e, de repente, goto tornou-se ruim... Ok, abusar do uso de goto pode mesmo tornar seu código ilegível, mas não há nada errado em usá-lo de forma razoável. Por exemplo: again: if ( connect( fd, (struct sockaddr *)&sin, sizeof sin ) ) goto again; ... Claro, isso poderia ser escrito em apenas uma linha: while ( connect( fd, (struct sockaddr *)&sin, sizeof sin ) ); Mas, note como no primeiro caso fica mais legível...
  16. O "crivo de Erastótenes" é um dos mais antigos algoritmos para teste primazia (século II A.E.C.). O teste anterior, diferente do crivo, não exige armazenamento temporário (array). O uso de um array é ruim para testes com valores muito altos. Claro, estou falando do algoritmo original.
  17. Aconselho a ver o texto no link... existem figuras feitas com o LaTeX no texto que o forum não sabe como lidar... Aconselho, também, aos admins do forum a instalarem algum plugin para conversão de latex amsmath equations para gráficos, ao estilo do Wordpress, por exemplo... Uma maneira de ver as "fórmulas" é usar o link https://www.codecogs.com/latex/eqneditor.php, fazer um Copy and Paste do código LaTeX para o site e ver a fórmula... mas, é mais fácil ver lá no #BitIsMyth! 🙂
  18. Artigo recente do #BitIsMyth: https://is.gd/kRROpi ---------------%<------- corte aqui --------------%<------------------------------- Não vou mostrar código aqui porque seria um bem grande e com alguns macetes e testes de condições especiais (como NaNs, overflows, underflows). Para dar uma olhada no código atual da glibc, obtenha o código-fonte (no Debian/Ubuntu: apt source libc6) e veja o arquivo stdlib/strtod_l.c. O problema em questão aqui é como transformar uma string contendo um valor decimal que tenha componente fracionário para ponto flutuante. Para tanto, usarei o tipo float como base (porque tem menos bits significativos – me permitirá escrever menos!). Considere o valor de PI com algumas “casas decimais” de “precisão”: 3.14159 Converter a parte inteira é trivial: Basta realizar múltiplas divisões por 2 e os restos nos darão os bits à partir do MSB. Neste caso, 3 é 0b11. Mas, e quanto a parte fracionária? O motivo que dividirmos por 2 o valor inteiro até obtermos zero como quociente é que cada posição do componente inteiro é um múltiplo de 2, em binário. Ou seja, 3 é . No caso da parte fracionária, os fatores multiplicadores dos bits são da ordem de . O expoente negativo indica que o valor de cada bit deverá ser dividido pela potência de dois. A operação inversa, então, é multiplicar o valor decimal fracionário por 2 e obter o valor inteiro que, necessariamente, será 0 ou 1. No caso, . Obtivemos 0, na parte inteira, e 0.28318 na parte fracionária… Esse 0, inteiro, é o MSB da parte fracionária… No segundo passo, multiplicamos apenas a parte fracionária resultante (0.28318) por 2. A parte inteira do resultado é o próximo bit e repetimos tudo para os próximos bits (eis todos os cálculos para 25 bits): 0.14159 * 2 = 0.28318 (MSB fracionario = 0) 0.28318 * 2 = 0.56636 (0) 0.56636 * 2 = 1.13272 (1) 0.13272 * 2 = 0.26544 (0) 0.26544 * 2 = 0.53088 (0) 0.53088 * 2 = 1.06176 (1) 0.06176 * 2 = 0.12352 (0) 0.12352 * 2 = 0.24704 (0) 0.24704 * 2 = 0.49408 (0) 0.49408 * 2 = 0.98816 (0) 0.98816 * 2 = 1.97632 (1) 0.97632 * 2 = 1.95264 (1) 0.95264 * 2 = 1.90528 (1) 0.09528 * 2 = 1.81056 (1) 0.81056 * 2 = 1.62112 (1) 0.62112 * 2 = 1.24224 (1) 0.24224 * 2 = 0.48448 (0) 0.48448 * 2 = 0.96896 (0) 0.96896 * 2 = 1.93792 (1) 0.93792 * 2 = 1.87584 (1) 0.87584 * 2 = 1.75168 (1) 0.75168 * 2 = 1.50336 (1) 0.50336 * 2 = 1.00672 (1) 0.00672 * 2 = 0.01344 (0) 0.01344 * 2 = 0.02688 (0) ... Assim o valor final de 3.14159 é, em binário, com 27 bits de precisão é 0b11.0010010000111111001111100. Como estamos lidando com float e já temos 2 bits na parte inteira, precisamos fazer essas repetições apenas 23 vezes. Uma vez a mais para determinar se precisaremos arredondar o valor obtido. Se a precisão de um float é de 24 bits, é necessário obter 25 para usar esse bit extra para arredondamento. Da sequência acima, obtemos o valor 0b11.00100100001111110011111. Agora, precisamos normalizar esse valor, deixando apenas 1 bit setado na parte inteira. Isso é feito deslocando o “ponto binário” 1 bit para a esquerda. O valor obtido é 0b1.10010010000111111001111_1. Como o bit inferior, além da precisão do float, ou seja, dos 23 bits da parte fracionária, é 1, arredonda-se o valor da “mantissa” (de 23 bits, em vermelho) para cima, acrescentando 1, obtendo: 0b1.10010010000111111010000. Agora, note que, na equação que nos dá o valor contido na estrutura de um float: O valor inteiro f nada mais é do que a parte fracionária, binária, deslocada 23 bits para a esquerda, ignorando o valor inteiro normalizado, ou seja, f é 0b100_1001_0000_1111_1101_0000 (0x490fd0 ou 4788176). Agora temos e : Que é a representação mais próxima de 3.14159 que podemos conseguir com um float. Neste ponto você deve estar pensando que é meio esquisito que uma rotina de conversão de string para ponto flutuante precise usar ponto flutuante. Isso é, mais ou menos, a história do ovo e da galinha (embora o “ovo” tenha surgido primeiro! A galinha evoluiu de outras espécies que botavam ovos!), mas a rotina geralmente usa aritmética de múltipla precisão e é até possível usar BCD (Binary Coded Decimal) para tanto… De novo, a rotina ____STR2F_INTERNAL() em strtod_l.c é bastante intrincada porque leva em contra aqueles underflows e overflows, mas também a notação xxx.xxx...E+/-eee, mas o princípio fundamental é esse ai em cima!
  19. Dica de funcionamento: Crie um arquivo texto com, por exemplo: 5 3 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Onde 5 e 3 é o número de carros (N) e voltas (M). As outras linhas os tempos das M voltas. Sem programa deve ser chamado assim: $ ./race < file.txt
  20. 1- Já que a entrada corresponde a linhas estruturadas, não há sentido em pedir os valores de forma interativa; 2- Você não precisa criar um array bidimensional, já que o tempo total gasto por cada carro é a soma dos tempos de cada volta. Ganha quem tiver tempo menor; Recomendo fazer um programa que leia stdin (usando scanf()) de acordo com a estrutura de entrada, faça os cálculos e retorne os valores desejados. PS: Você não especificou as restrições... Pode-se usar alocação dinâmica, por exemplo? PS2: Well.... EU não vou fazer o exercício proce
  21. Acredito que devam existir regras numa competição. Se realmente puder escolher uma "linguagem", apresente sua implementação em russo e use uma linguagem de programação obscura como MUMPS, Parasol, C@+, FORTH, APL, Brainfuck... Vai ser um sucesso...
  22. Grande Felipe, você é muito mais paciente que eu... também pensei em passar o troço pelo pré-processador (cpp - c pre processor)... mas não tive paciência pra isso! 🙂
×
×
  • Create New...