#!/usr/bin/perl
#
# -----------------------COMENTARIO GLOBAL-----------------------
# ---------------------------------------------------------------
# PROPOSITO
# ---------
# Genera thumbnails de un video y un descriptor VTT
# También genera un screenshot o poster del video
# Proceso:
# -obtener ruta del video
# -leer resolucion y fps de mp4
# -determinar nueva resolucion de thumbnail
# -determinar intervalo de frames a los que hay que sacar imagen
# -determinar cuantas thumbnails habran
# -generar archivo vtt segun la cantidad de frames sacados
# -generar marca xdata para el prontus
# -actualizar articulo
# ejemplo de comando ffmpeg para generar thumbnails:
# ffmpeg -i video.mp4 -vf "select=not(mod(n\,150)),scale=150:-1,tile=4x5" -vsync 0 out%d.jpg
# ejemplo de invocacion por linea de comandos:
# perl prontus_genera_thumbnailsvideo.pl /var/www/misitio.cl/web/<prontus_id>/site/mm/20171207/mmedia/multimedia_video120171207175743.mp4
#
# ---------------------------------------------------------------
# INVOCACIONES ACEPTADAS.
# -----------------------
#
# ---------------------------------------------------------------
# PLANTILLAS HTML UTILIZADAS.
# ---------------------------
#
#
# -------------------------------BEGIN SCRIPT--------------------
# ---------------------------------------------------------------
# DECLARACIONES GLOBALES.
# ------------------------
use strict;
use utf8;

BEGIN {
    use FindBin qw($Bin);
    my $pathLibsProntus = $Bin;
    unshift(@INC,$pathLibsProntus); # Para dejar disponibles las librerias del directorio
    $pathLibsProntus =~ s/\/[^\/]+\/?$//;
    unshift(@INC,$pathLibsProntus); # Para dejar disponibles las librerias de prontus
}

use POSIX qw(ceil floor);
use lib_stdlog;
&lib_stdlog::set_stdlog($0, 51200);

use prontus_varglb; &prontus_varglb::init();
use Artic;
use lib_mam;
use lib_prontus;
use lib_xcoding;
use glib_fildir_03;

my $TS          = '';
my $PRONTUS_ID  = '';
my $WIDTH_THUMB = 160;
my $XML_ART = '';
my $REGEN_VISTA_ART = 0;

# Este script genera las thumbnails de un video pasado. Corre exclusivamente por CLI.
# Parámetro:
# ruta completa hacia el archivo de video a procesar, e.g. /[prontus]/site/artic/[yyyymmdd]/mmedia/multimedia_video[numero][timestamp][.ext]
main:{
    if (&myself_running() > 1) {
        exit;
    }

    while(&faststart_running()) {
        sleep(5);
    }


    my $fullpath_video = $ARGV[0];
    # indica si se debe regenerar la vista del articulo
    $REGEN_VISTA_ART = $ARGV[1];

    my $fechac;
    my $marca_video;
    my $video = '';
    # se usa | como delimitador para facilitar la regexp
    if ($fullpath_video =~ m|^/[\w\.\-\/]*/([\w\_\-]+?)/site/\w+/(\d{8})/mmedia/(multimedia_video\w+)(\d{14})(\.\w+)$|) {
        $PRONTUS_ID = $1;
        $fechac = $2;
        $marca_video = $3;
        $TS = $4;
        # guardamos el nombre del video
        $video = "$3$4$5";
    } else {
        print STDERR "Error al leer el TS del archivo de entrada [$fullpath_video]\n";
        exit;
    }

    # Carga variables de configuracion.
    my $msg_load = &lib_prontus::load_config_by_id($PRONTUS_ID);
    if ($msg_load ne '') {
        print STDERR "No se pudo cargar la configuracion de prontus $PRONTUS_ID\n";
    }

    # verifica existencia
    if (! -s $fullpath_video) {
        print STDERR "No se encuentra el video indicado [$marca_video] [$video] [$fullpath_video]\n";
        exit;
    }

    #cargamos el xml
    $XML_ART = &glib_fildir_03::read_file("$prontus_varglb::DIR_SERVER$prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_SITE'}/artic/$fechac/xml/$TS.xml");
    if ($XML_ART !~ /<$marca_video>$video<\/$marca_video>/is ) {
        print STDERR "No hay video en el articulo [$TS] [$marca_video] [$video]\n";
        exit;
    }

    # obtenemos las caracteristicas del video
    my ($width, $height, $vcodec, $acodec, $vbitrate, $abitrate, $fps, $duration) = &lib_xcoding::get_info_media($fullpath_video);

    # si no se determinan los fps del video asumimos 30
    if ($fps == 0) {
        print STDERR "No se pudo determinar FPS de [$fullpath_video]\n";
        $fps = 30;
    }
    # calcular las dimensiones del thumb.
    my ($new_width, $new_height);
    if ($width > $WIDTH_THUMB || ($width %2 != 0) || ($height %2 != 0) ) {
        $new_width = $width;
        $new_height = $height;
        if ($new_width > $WIDTH_THUMB) {
            $new_width = $WIDTH_THUMB;
            $new_height = int ($WIDTH_THUMB*$height/$width);
            if ($new_height %2 != 0){
                $new_height +=1;
            }
        } else {
            if ($new_width %2 != 0) {
                $new_width += 1;
            }
            if ($new_height%2 != 0) {
                $new_height += 1;
            }
        }
    }

    # numero de frames cada 5 segundos;
    my $frames = $fps *5;
    $frames = ceil($frames);
    my $output_file = "$marca_video$TS\_thumbs%04d.jpg";

    # verificamos el directorio de salida
    my $dst_dir = "/$prontus_varglb::PRONTUS_ID$prontus_varglb::DIR_SITE$prontus_varglb::DIR_EXMEDIA/$fechac$prontus_varglb::DIR_THUMBS";
    if (! &glib_fildir_03::check_dir("$prontus_varglb::DIR_SERVER$dst_dir")) {
        print STDERR "ERROR: No se pudo crear el directorio [$prontus_varglb::DIR_SERVER$dst_dir]\n";
        exit;
    }

    # calcula el total de imagenes que se deben generar
    # divide la duracion por 36 thumbnails cada 5 segundos
    # redondea a entero superior
    my $thumbnails = ceil($duration/(5*36));

    # obtenemos el path de nice
    my $pathnice = &lib_prontus::get_path_nice();
    $pathnice = "$pathnice -n19 " if($pathnice);

    # generamos los thumbnails
    my $cmd = "$pathnice $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_FFMPEG'}/ffmpeg -ss 00:00:01 -i $fullpath_video -an -vf \"select=not(mod(n\\,$frames)),scale=$new_width:$new_height,tile=6x6\" -vsync 0 $prontus_varglb::DIR_SERVER$dst_dir/$output_file 2>&1";
    print STDERR "[$cmd]\n";

    my @result = `$cmd`;
    if ($? != 0) {
        # se verifica error en la ejecucion
        foreach (@result) {
            if ($_ =~ m/[^W]error/is) {
                print STDERR "ERROR encontrado: [". join(" ", @result)."]\n";
                print STDERR "ERROR: No se generan thumbnails para [$TS][$marca_video]\n";
                exit;
            }
        }
    }

    my $web_vtt = "WEBVTT\n";
    my $thumb_file;
    my $counter = 0;
    # se genera el archivo .vtt
    for (my $h = 1; $h <= $thumbnails;$h++) {
        $thumb_file = sprintf($output_file, $h);
        if (!-s "$prontus_varglb::DIR_SERVER$dst_dir/$thumb_file") {
            print STDERR "ERROR: no se ha generado [$prontus_varglb::DIR_SERVER$dst_dir/$thumb_file]\n";
            last;
        }
        &lib_prontus::purge_cache("$dst_dir/$thumb_file");
        for (my $y = 0; $y < 6; $y++) {
            for (my $x = 0; $x < 6; $x++) {
                # formato de referencia: 00:00.000 --> 00:05.000
                $web_vtt .= "\n".&lib_xcoding::format_time($counter) .' --> ';
                $counter += 5;
                if ($counter > $duration) {
                    $web_vtt .= &lib_xcoding::format_time($duration) ."\n";
                    $web_vtt .= "$thumb_file#xywh=".$new_width*$x. ",".$new_height*$y.",$new_width,$new_height\n";
                    last;
                }
                $web_vtt .= &lib_xcoding::format_time($counter)."\n";
                $web_vtt .= "$thumb_file#xywh=".$new_width*$x. ",".$new_height*$y.",$new_width,$new_height\n";
            }
            if ($counter > $duration) {
                last;
            }
        }
    }
    &glib_fildir_03::write_file("$prontus_varglb::DIR_SERVER$dst_dir/$marca_video$TS\_thumbs.vtt", $web_vtt);
    &lib_prontus::purge_cache("$dst_dir/$marca_video$TS\_thumbs.vtt");

    # generamos poster del video
    my $tiempo = $duration/2;
    $output_file = "$marca_video$TS.jpg";
    $cmd = "$prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'DIR_FFMPEG'}/ffmpeg -ss $tiempo -i $fullpath_video -y -vframes 1 -f image2 $prontus_varglb::DIR_SERVER$dst_dir/$output_file 2>&1";
    print STDERR "[$cmd]\n";

    @result = `$cmd`;
    if ($? != 0) {
        # se verifica error en la ejecucion
        foreach (@result) {
            if ($_ =~ m/[^W]error/is) {
                print STDERR "ERROR encontrado: [". join(" ", @result)."]\n";
                print STDERR "ERROR: No se generan thumbnails para [$TS][$marca_video]\n";
                exit;
            }
        }
    }
    &lib_xcoding::genera_info_media($fullpath_video);

    &actualizar_articulo() if ($REGEN_VISTA_ART);
}

# ---------------------------------------------------------------
sub actualizar_articulo {
    my $artic_obj = Artic->new(
                'prontus_id'         => $prontus_varglb::PRONTUS_ID,
                'public_server_name' => $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'PUBLIC_SERVER_NAME'},
                'cpan_server_name'   => $prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'CPAN_SERVER_NAME'},
                'document_root'      => $prontus_varglb::DIR_SERVER,
                'ts'                 => $TS,
                'no_check_dirs'      => 1) || return "Error inicializando objeto articulo: $Artic::ERR TS[$TS]";

    $lib_prontus::ARTICS{$prontus_varglb::PRONTUS_ID}{$TS} = $artic_obj;

    # Generar vista (a partir del xml)
    $artic_obj->generar_vista_art('') || return $Artic::ERR;

    my %datos = &lib_prontus::getCamposXml($XML_ART, '_fid,_plt');
    my $fid = $datos{'_fid'};
    my $plt = $datos{'_plt'};

    # Parsear plantillas paralelas.

    foreach my $plt_paralela (@{$prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'FORM_PLTS'}{$fid}{'plt_paralela'}}) {
        $artic_obj->generar_vista_art('', $plt_paralela, 1) || return $Artic::ERR;
    }

    # Generar vistas secundarias
    foreach my $mv (keys %{$prontus_varglb::CONFIG{$prontus_varglb::PRONTUS_ID}{'MULTIVISTAS'}}) {
        $artic_obj->generar_vista_art($mv) || return $Artic::ERR;
    }

    return '';
}

# ---------------------------------------------------------------
# Detecta cuantas copias de este script estan corriendo.
sub myself_running {
    my(@result) = qx/ps axww | grep $0 | grep $ARGV[0] | grep -v ' grep ' | grep -v 'nice' | grep -v 'editor' | grep -v 'sh -c' | grep -v execIfMaster | grep -v 'tail'/; # wc -l
    my $res = 0;
    foreach my $line (@result) {
        #print "line = [$line] [$0]\n";
        if ($line =~ /$0/) {
            $res++;
        }
    }
    return $res;
}
# ---------------------------------------------------------------
# Detecta si esta corriento el qtfaststart
sub faststart_running {
    my(@result) = qx/ps axww | grep qtfaststart.cgi | grep $ARGV[0] | grep -v ' grep ' | grep -v 'nice' | grep -v 'editor' | grep -v 'sh -c' | grep -v execIfMaster | grep -v 'tail'/; # wc -l
    my $res = 0;
    foreach my $line (@result) {
        #print "line = [$line] [$0]\n";
        if ($line =~ /$0/) {
            $res++;
        }
    }
    return $res;
}
