/*
 * Identify Hook
 * Copyright (c) 2007 Tracey Jaquith myfirstname(at)archive.org
 *
 * Tired of screen-scraping the output of ffmpeg and/or mplayer
 * to get the parameters / clip info for a media file?
 * This hook attempts to remedy this by printing simple
 * information about the passed in filename from the cmd line.
 *
 * Example usage:
 *  ffmpeg -vhook "[prefixdir]/lib/vhook/identify.so input.avi"
 *
 * To compile .c to a .so library:
 *    unpack source of ffmpeg and chdir to it
 *    cd vhook/
 *    ln -s /petabox/deriver/identify.c
 *    add "identify$(SLIBSUF)" to end of link "HOOKS=" in "Makefile"
 *    make
 *
 * Note that the entire vhook argument is encapsulated in ''. This
 * way, arguments to the vhook won't be mixed up with those for ffmpeg.
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>

#include "common.h"
#include "avformat.h"
#include "framehook.h"

typedef struct
{
  AVFormatContext *pFormatCtx;
} ContextInfo;

int myerr(char *str);


int Configure(void **ctxp, int argc, char *argv[])
{
  ContextInfo *ci;
  AVStream    *st;
  int i, videoStream;
  int hasAudio=0;
  char buf[BUFSIZ+1];
  double tmp;

  if (0 == (*ctxp = av_mallocz(sizeof(ContextInfo)))) return -1;
  ci = (ContextInfo *) *ctxp;

  if (argc != 2)
    return myerr("requires filename argument");

  if (av_open_input_file(&ci->pFormatCtx, argv[1], NULL, 0, NULL) != 0)
  {
    snprintf(buf, BUFSIZ, "failed to open file: %s", argv[1]);
    return myerr(buf);
  }

  if (av_find_stream_info(ci->pFormatCtx)<0)
    return myerr("failed to find stream info");

  // To make things nice and easy, we simply use the first video stream we find
  videoStream = -1;
  for (i=0; i < ci->pFormatCtx->nb_streams; i++)
  {
    if (ci->pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
    {
      if (videoStream == -1)
        videoStream = i;
    }
    else if (ci->pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
    {
      hasAudio = 1;
    }
  }
  if (videoStream == -1)
    return myerr("failed to find any video stream");


  st = ci->pFormatCtx->streams[videoStream];


  avcodec_string(buf, sizeof(buf), st->codec, 1);
  av_log(NULL, AV_LOG_INFO, "%s", buf);
     

  av_log(NULL, AV_LOG_INFO, "\nwidth: %d\nheight: %d\n",
         st->codec->width, st->codec->height);

  // output sample video aspect ratio information so we can determine
  // if the pixels should be scaled or be considered "AS IS"
  if (st->codec->sample_aspect_ratio.num > 0  &&
      st->codec->sample_aspect_ratio.den > 0)
  {
    // AVCodecContext *codec   libavcodec/avcodec.h
    AVRational a;
    a.num = st->codec->width;
    a.den = 1;

    av_log(NULL, AV_LOG_INFO, "aspect: %d/%d\n",
           st->codec->sample_aspect_ratio.num,
           st->codec->sample_aspect_ratio.den);
  }
  

  // essentially from libavformat/utils.c
  tmp = (st->r_frame_rate.den && st->r_frame_rate.num ?
         av_q2d(st->r_frame_rate) :
         1/av_q2d(st->codec->time_base));
  av_log(NULL, AV_LOG_INFO, "fps: %5.2f\n", tmp);
  
  // from libavformat/utils.c (nearly direct copy)
  av_log(NULL, AV_LOG_INFO, "duration: ");
  if (ci->pFormatCtx->duration != AV_NOPTS_VALUE)
  {
    int hours, mins, secs, us;
    secs = ci->pFormatCtx->duration / AV_TIME_BASE;
    us =   ci->pFormatCtx->duration % AV_TIME_BASE;
    mins = secs / 60;
    secs %= 60;
    hours = mins / 60;
    mins %= 60;
    av_log(NULL, AV_LOG_INFO, "%02d:%02d:%02d.%01d\n", hours, mins, secs,
           (10 * us) / AV_TIME_BASE);
  }
  else
  {
    av_log(NULL, AV_LOG_INFO, "N/A\n");
  }

  av_log(NULL, AV_LOG_INFO, "audio: %s\n", (hasAudio > 0 ? "true":"false"));
    
  
  return -1;
}

void Process(void *ctx, AVPicture *picture,  enum PixelFormat pix_fmt,
             int src_width, int src_height, int64_t pts)
{
}

void Release(void *ctx)
{
  av_free(ctx);
}


int myerr(char *str)
{
  av_log(NULL, AV_LOG_ERROR, "\n\n[identify vhook] %s\n\n", str);
  return -1;
}
