[xiph-commits] r15976 - in trunk/ffmpeg2theora: . src

j at svn.xiph.org j at svn.xiph.org
Fri May 1 08:22:10 PDT 2009


Author: j
Date: 2009-05-01 08:22:09 -0700 (Fri, 01 May 2009)
New Revision: 15976

Added:
   trunk/ffmpeg2theora/src/avinfo.c
   trunk/ffmpeg2theora/src/avinfo.h
Modified:
   trunk/ffmpeg2theora/ffmpeg2theora.1
   trunk/ffmpeg2theora/get_ffmpeg_svn.sh
   trunk/ffmpeg2theora/src/ffmpeg2theora.c
Log:
* update ffmpeg script to get latest 0.5 version from svn
* use av_audio_resample_init
* new option to output information about files as json array



Modified: trunk/ffmpeg2theora/ffmpeg2theora.1
===================================================================
--- trunk/ffmpeg2theora/ffmpeg2theora.1	2009-05-01 11:56:03 UTC (rev 15975)
+++ trunk/ffmpeg2theora/ffmpeg2theora.1	2009-05-01 15:22:09 UTC (rev 15976)
@@ -216,6 +216,9 @@
 .TP
 .B \-h, \-\-help
 Output a help message.
+.TP
+.B \-\-info
+Output json info about input file, use -o to save json to file.
 .SH EXAMPLES
 Encode Videos:
   ffmpeg2theora videoclip.avi (will write output to videoclip.ogv)

Modified: trunk/ffmpeg2theora/get_ffmpeg_svn.sh
===================================================================
--- trunk/ffmpeg2theora/get_ffmpeg_svn.sh	2009-05-01 11:56:03 UTC (rev 15975)
+++ trunk/ffmpeg2theora/get_ffmpeg_svn.sh	2009-05-01 15:22:09 UTC (rev 15976)
@@ -16,12 +16,15 @@
 uname | grep MINGW && options="$common --enable-memalign-hack --enable-mingw32 --extra-cflags=-I/usr/local/include --extra-ldflags=-L/usr/local/lib $extra"
 
 # load FFMPEG specific properties
-. ./ffmpegrev
+#. ./ffmpegrev
 
 #Get ffmpeg from svn
-svn -r $FFMPEG_REVISION co $FFMPEG_SVN $FFMPEG_CO_DIR
-svn update -r $FFMPEG_EXTERNALS_REVISION $FFMPEG_CO_DIR/libswscale
+#svn -r $FFMPEG_REVISION co $FFMPEG_SVN $FFMPEG_CO_DIR
+#svn update -r $FFMPEG_EXTERNALS_REVISION $FFMPEG_CO_DIR/libswscale
 
+#get latest version from 0.5 branch
+svn co svn://svn.ffmpeg.org/ffmpeg/branches/0.5 ffmpeg
+
 #configure and build ffmpeg
 cd ffmpeg && ./configure $options && make
 

Added: trunk/ffmpeg2theora/src/avinfo.c
===================================================================
--- trunk/ffmpeg2theora/src/avinfo.c	                        (rev 0)
+++ trunk/ffmpeg2theora/src/avinfo.c	2009-05-01 15:22:09 UTC (rev 15976)
@@ -0,0 +1,322 @@
+/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
+/*
+ * ffmpeg2theora.c -- Convert ffmpeg supported a/v files to Ogg Theora / Ogg Vorbis
+ * Copyright (C) 2003-2008 <j at v2v.cc>
+ *
+ * gcc -o avinfo avinfo.c `pkg-config --cflags --libs libavcodec libavformat`
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <math.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "libavformat/avformat.h"
+
+long get_filesize(char const *filename) {
+    struct stat file;
+    if(!stat(filename,&file)) {
+        return file.st_size;
+    }
+    return 0;
+}
+
+char const *fix_codec_name(char const *codec_name) {
+    if (!strcmp(codec_name, "libschrodinger")) {
+        codec_name = "dirac";
+    }
+    else if (!strcmp(codec_name, "vp6f")) {
+        codec_name = "vp6";
+    }
+    else if (!strcmp(codec_name, "mpeg2video")) {
+        codec_name = "mpeg2";
+    }
+    else if (!strcmp(codec_name, "mpeg1video")) {
+        codec_name = "mpeg1";
+    }
+    else if (!strcmp(codec_name, "0x0000")) {
+        codec_name = "mu-law";
+    }
+   return codec_name;
+}
+
+enum {
+    JSON_STRING,
+    JSON_INT,
+    JSON_FLOAT,
+} JSON_TYPES;
+
+void json_add_key_value(FILE *output, char *key, void *value, int type) {
+    switch(type) {
+        case JSON_STRING:
+            fprintf(output, "  \"%s\": \"%s\",\n", key, (char *)value);
+            break;
+        case JSON_INT:
+            fprintf(output, "  \"%s\": %d,\n", key, *(int *)value);
+            break;
+        case JSON_FLOAT:
+            fprintf(output, "  \"%s\": %f,\n", key, *(float *)value);
+            break;
+    }
+}
+
+void json_codec_info(FILE *output, AVCodecContext *enc) {
+    const char *codec_name;
+    AVCodec *p;
+    char buf1[32];
+    int bitrate;
+    AVRational display_aspect_ratio;
+
+    p = avcodec_find_decoder(enc->codec_id);
+
+    if (p) {
+        codec_name = p->name;
+    } else if (enc->codec_id == CODEC_ID_MPEG2TS) {
+        /* fake mpeg2 transport stream codec (currently not
+           registered) */
+        codec_name = "mpeg2ts";
+    } else if (enc->codec_name[0] != '\0') {
+        codec_name = enc->codec_name;
+    } else {
+        /* output avi tags */
+        if(   isprint(enc->codec_tag&0xFF) && isprint((enc->codec_tag>>8)&0xFF)
+           && isprint((enc->codec_tag>>16)&0xFF) && isprint((enc->codec_tag>>24)&0xFF)){
+            snprintf(buf1, sizeof(buf1), "%c%c%c%c / 0x%04X",
+                     enc->codec_tag & 0xff,
+                     (enc->codec_tag >> 8) & 0xff,
+                     (enc->codec_tag >> 16) & 0xff,
+                     (enc->codec_tag >> 24) & 0xff,
+                      enc->codec_tag);
+        } else {
+            snprintf(buf1, sizeof(buf1), "0x%04x", enc->codec_tag);
+        }
+        codec_name = buf1;
+    }
+
+    switch(enc->codec_type) {
+    case CODEC_TYPE_VIDEO:
+        codec_name = fix_codec_name(codec_name);
+        json_add_key_value(output, "video_codec", (void *)codec_name, JSON_STRING);
+        if (enc->pix_fmt != PIX_FMT_NONE) {
+            json_add_key_value(output, "pixel_format", (void *)avcodec_get_pix_fmt_name(enc->pix_fmt), JSON_STRING);
+        }
+        if (enc->width) {
+            json_add_key_value(output, "width", &enc->width, JSON_INT);
+            json_add_key_value(output, "height", &enc->height, JSON_INT);
+            if (enc->sample_aspect_ratio.num) {
+                av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
+                          enc->width*enc->sample_aspect_ratio.num,
+                          enc->height*enc->sample_aspect_ratio.den,
+                          1024*1024);
+                snprintf(buf1, sizeof(buf1), "%d:%d",
+                         enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den);
+                json_add_key_value(output, "pixel_aspect_ratio", buf1, JSON_STRING);
+                snprintf(buf1, sizeof(buf1), "%d:%d",
+                         display_aspect_ratio.num, display_aspect_ratio.den);
+                json_add_key_value(output, "display_aspect_ratio", buf1, JSON_STRING);
+            }
+        }
+        bitrate = enc->bit_rate;
+        if (bitrate != 0) {
+            float t = (float)bitrate / 1000;
+            json_add_key_value(output, "video_bitrate", &t, JSON_FLOAT);
+        }
+        break;
+    case CODEC_TYPE_AUDIO:
+        codec_name = fix_codec_name(codec_name);
+        json_add_key_value(output, "audio_codec", (void *)codec_name, JSON_STRING);
+        if (enc->sample_rate) {
+            json_add_key_value(output, "samplerate", &enc->sample_rate, JSON_INT);
+        }
+        json_add_key_value(output, "channels", &enc->channels, JSON_INT);
+
+        /* for PCM codecs, compute bitrate directly */
+        switch(enc->codec_id) {
+        case CODEC_ID_PCM_F64BE:
+        case CODEC_ID_PCM_F64LE:
+            bitrate = enc->sample_rate * enc->channels * 64;
+            break;
+        case CODEC_ID_PCM_S32LE:
+        case CODEC_ID_PCM_S32BE:
+        case CODEC_ID_PCM_U32LE:
+        case CODEC_ID_PCM_U32BE:
+        case CODEC_ID_PCM_F32BE:
+        case CODEC_ID_PCM_F32LE:
+            bitrate = enc->sample_rate * enc->channels * 32;
+            break;
+        case CODEC_ID_PCM_S24LE:
+        case CODEC_ID_PCM_S24BE:
+        case CODEC_ID_PCM_U24LE:
+        case CODEC_ID_PCM_U24BE:
+        case CODEC_ID_PCM_S24DAUD:
+            bitrate = enc->sample_rate * enc->channels * 24;
+            break;
+        case CODEC_ID_PCM_S16LE:
+        case CODEC_ID_PCM_S16BE:
+        case CODEC_ID_PCM_S16LE_PLANAR:
+        case CODEC_ID_PCM_U16LE:
+        case CODEC_ID_PCM_U16BE:
+            bitrate = enc->sample_rate * enc->channels * 16;
+            break;
+        case CODEC_ID_PCM_S8:
+        case CODEC_ID_PCM_U8:
+        case CODEC_ID_PCM_ALAW:
+        case CODEC_ID_PCM_MULAW:
+        case CODEC_ID_PCM_ZORK:
+            bitrate = enc->sample_rate * enc->channels * 8;
+            break;
+        default:
+            bitrate = enc->bit_rate;
+            break;
+        }
+        if (bitrate != 0) {
+            float t = (float)bitrate / 1000;
+            json_add_key_value(output, "audio_bitrate", &t, JSON_FLOAT);
+        }
+        break;
+    /*
+    case CODEC_TYPE_DATA:
+        fprintf(output, "datacodec: %s\n", codec_name);
+        bitrate = enc->bit_rate;
+        break;
+    case CODEC_TYPE_SUBTITLE:
+        fprintf(output, "subtitle: %s\n", codec_name);
+        bitrate = enc->bit_rate;
+        break;
+    case CODEC_TYPE_ATTACHMENT:
+        fprintf(output, "attachment: : %s\n", codec_name);
+        bitrate = enc->bit_rate;
+        break;
+    */
+    default:
+        //FIXME: ignore unkown for now
+        /*
+        snprintf(buf, buf_size, "Invalid Codec type %d", enc->codec_type);
+        */
+        return;
+    }
+}
+
+
+static void json_stream_format(FILE *output, AVFormatContext *ic, int i) {
+    char buf[1024];
+    char buf1[32];
+    int flags = ic->iformat->flags;
+    AVStream *st = ic->streams[i];
+    int g = av_gcd(st->time_base.num, st->time_base.den);
+    AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL, 0);
+    json_codec_info(output, st->codec);
+    if (st->sample_aspect_ratio.num && // default
+        av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) {
+        AVRational display_aspect_ratio;
+        av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
+                  st->codec->width*st->sample_aspect_ratio.num,
+                  st->codec->height*st->sample_aspect_ratio.den,
+                  1024*1024);
+        snprintf(buf1, sizeof(buf1), "%d:%d",
+                 st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
+        json_add_key_value(output, "pixel_aspect_ratio", buf1, JSON_STRING);
+        snprintf(buf1, sizeof(buf1), "%d:%d",
+                 display_aspect_ratio.num, display_aspect_ratio.den);
+        json_add_key_value(output, "display_aspect_ratio", buf1, JSON_STRING);
+    }
+    if(st->codec->codec_type == CODEC_TYPE_VIDEO){
+        if (st->time_base.den && st->time_base.num && av_q2d(st->time_base) > 0.001) {
+            snprintf(buf1, sizeof(buf1), "%d:%d",
+                     st->time_base.den, st->time_base.num);
+            json_add_key_value(output, "framerate", buf1, JSON_STRING);
+        } else {
+            snprintf(buf1, sizeof(buf1), "%d:%d",
+                     st->r_frame_rate.num, st->r_frame_rate.den);
+            json_add_key_value(output, "framerate", buf1, JSON_STRING);
+        }
+    }
+}
+
+/* "user interface" functions */
+void json_format_info(FILE* output, AVFormatContext *ic, const char *url) {
+    int i;
+    long filesize;
+
+    fprintf(output, "{\n");
+    json_add_key_value(output, "path", (void *)url, JSON_STRING);
+    filesize = get_filesize(url);
+    json_add_key_value(output, "size", &filesize, JSON_INT);
+
+    if (ic->duration != AV_NOPTS_VALUE) {
+        float secs;
+        secs = (float)ic->duration / AV_TIME_BASE;
+        json_add_key_value(output, "duration", &secs, JSON_FLOAT);
+    } else {
+        float t = -1;
+        json_add_key_value(output, "duration", &t, JSON_FLOAT);
+    }
+    if (ic->bit_rate) {
+        float t = (float)ic->bit_rate / 1000;
+        json_add_key_value(output, "bitrate", &t, JSON_FLOAT);
+    }
+
+    if(ic->nb_programs) {
+        int j, k;
+        for(j=0; j<ic->nb_programs; j++) {
+            for(k=0; k<ic->programs[j]->nb_stream_indexes; k++)
+                json_stream_format(output, ic, ic->programs[j]->stream_index[k]);
+         }
+    } else {
+        for(i=0;i<ic->nb_streams;i++) {
+            json_stream_format(output, ic, i);
+        }
+    }
+    fprintf(output, "}\n");
+}
+
+// uncomment this block to use avinfo on its own
+/*
+int main(int argc, char **argv) {
+    char inputfile_name[255];
+    AVInputFormat *input_fmt = NULL;
+    AVFormatParameters *formatParams = NULL;
+    AVFormatContext *context;
+    FILE* output = stdout;
+    
+    avcodec_register_all();
+    av_register_all();
+
+    if(argc == 1) {
+        fprintf(stderr, "usage: %s avfile [outputfile]\n", argv[0]);
+        exit(1);
+    }
+    snprintf(inputfile_name, sizeof(inputfile_name),"%s", argv[1]);
+    if(argc == 3) {
+        output = fopen(argv[2], "w");
+    }
+    
+    if (av_open_input_file(&context, inputfile_name, input_fmt, 0, formatParams) >= 0) {
+        if (av_find_stream_info(context) >= 0) {
+            json_format_info(output, context, inputfile_name);
+        }
+    }
+    if(output != stdout) {
+        fclose(output);
+    }
+}
+*/

Added: trunk/ffmpeg2theora/src/avinfo.h
===================================================================
--- trunk/ffmpeg2theora/src/avinfo.h	                        (rev 0)
+++ trunk/ffmpeg2theora/src/avinfo.h	2009-05-01 15:22:09 UTC (rev 15976)
@@ -0,0 +1,6 @@
+#ifndef _F2T_AVINFO_H_
+#define _F2T_AVINFO_H_
+
+void json_format_info(FILE* output, AVFormatContext *ic, const char *url);
+
+#endif

Modified: trunk/ffmpeg2theora/src/ffmpeg2theora.c
===================================================================
--- trunk/ffmpeg2theora/src/ffmpeg2theora.c	2009-05-01 11:56:03 UTC (rev 15975)
+++ trunk/ffmpeg2theora/src/ffmpeg2theora.c	2009-05-01 15:22:09 UTC (rev 15976)
@@ -47,6 +47,7 @@
 #include "iso639.h"
 #include "subtitles.h"
 #include "ffmpeg2theora.h"
+#include "avinfo.h"
 
 enum {
     NULL_FLAG,
@@ -75,7 +76,8 @@
     FRONTENDFILE_FLAG,
     SPEEDLEVEL_FLAG,
     PP_FLAG,
-    NOSKELETON
+    NOSKELETON,
+    INFO_FLAG
 } F2T_FLAGS;
 
 enum {
@@ -746,8 +748,6 @@
         if (this->sample_rate==-1) {
             this->sample_rate = aenc->sample_rate;
         }
-        if (this->channels != aenc->channels && aenc->codec_id == CODEC_ID_AC3)
-            aenc->channels = this->channels;
 
         if (this->no_upscaling) {
             if (this->sample_rate > aenc->sample_rate)
@@ -758,7 +758,14 @@
 
         if (acodec != NULL && avcodec_open (aenc, acodec) >= 0) {
             if (this->sample_rate != aenc->sample_rate || this->channels != aenc->channels) {
-                this->audio_resample_ctx = audio_resample_init (this->channels,aenc->channels,this->sample_rate,aenc->sample_rate);
+                // values take from libavcodec/resample.c
+                this->audio_resample_ctx = av_audio_resample_init(this->channels,    aenc->channels,
+                                                                  this->sample_rate, aenc->sample_rate,
+                                                                  SAMPLE_FMT_S16,    aenc->sample_fmt,
+                                                                  16, 10, 0, 0.8);
+                if (!this->audio_resample_ctx) {
+                    this->channels = aenc->channels;
+                }
                 if (this->sample_rate!=aenc->sample_rate)
                     fprintf(stderr, "  Resample: %dHz => %dHz\n",aenc->sample_rate,this->sample_rate);
                 if (this->channels!=aenc->channels)
@@ -1031,19 +1038,6 @@
             }
 
             /* check for end time */
-            /*
-            
-            if (info.audio_only && no_samples > 0) {
-                if (this->sample_count >= no_samples) {
-                    break;
-                }
-            }
-            if (info.video_only && no_frames > 0) {
-                if (this->frame_count > no_frames) {
-                    break;
-                }
-            }
-            */
             if (no_frames > 0 && this->frame_count == no_frames) {
                 video_eos = 1;
             }
@@ -1562,7 +1556,6 @@
         "      --sync             use A/V sync from input container. Since this does\n"
         "                          not work with all input format you have to manually\n"
         "                          enable it if you have issues with A/V sync\n"
-        "\n"
 #ifdef HAVE_KATE
         "Subtitles options:\n"
         "      --subtitles file                 use subtitles from the given file (SubRip (.srt) format)\n"
@@ -1590,7 +1583,9 @@
 #endif
         "  -P, --pid fname        write the process' id to a file\n"
         "  -h, --help             this message\n"
+        "      --info             output json info about input file, use -o to save json to file\n"
         "\n"
+        "\n"
         "Examples:\n"
         "  ffmpeg2theora videoclip.avi (will write output to videoclip.ogv)\n"
         "\n"
@@ -1623,6 +1618,7 @@
     char outputfile_name[255];
     char inputfile_name[255];
     char *str_ptr;
+    int output_json = 0;
 
     static int flag = -1;
     static int metadata_flag = 0;
@@ -1685,7 +1681,7 @@
         {"speedlevel",required_argument,&flag,SPEEDLEVEL_FLAG},
         {"frontend",0,&flag,FRONTEND_FLAG},
         {"frontendfile",required_argument,&flag,FRONTENDFILE_FLAG},
-
+        {"info",no_argument,&flag,INFO_FLAG},
         {"artist",required_argument,&metadata_flag,10},
         {"title",required_argument,&metadata_flag,11},
         {"date",required_argument,&metadata_flag,12},
@@ -1812,6 +1808,9 @@
                         case NOSKELETON:
                             info.with_skeleton=0;
                             break;
+                        case INFO_FLAG:
+                            output_json = 1;
+                            break;
 #ifdef HAVE_KATE
                         case SUBTITLES_FLAG:
                             set_subtitles_file(convert,optarg);
@@ -2057,6 +2056,10 @@
         }
     }
 
+    if (output_json && !outputfile_set) {
+        snprintf(outputfile_name, sizeof(outputfile_name), "-");
+        outputfile_set = 1;
+    }
     while(optind<argc) {
         /* assume that anything following the options must be a filename */
         snprintf(inputfile_name,sizeof(inputfile_name),"%s",argv[optind]);
@@ -2143,6 +2146,13 @@
                 }
                 info.outfile = fopen(outputfile_name,"wb");
 #endif
+                if (output_json) {
+                    json_format_info(info.outfile, convert->context, inputfile_name);
+                    if (info.outfile != stdout)
+                        fclose(info.outfile);
+                    exit(0);
+                }
+
                 if (info.frontend) {
                     fprintf(info.frontend, "\nf2t ;duration: %d;\n", (int)(convert->context->duration / AV_TIME_BASE));
                     fflush(info.frontend);



More information about the commits mailing list