[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