Commit 0b7479a2 authored by Jan Gerber's avatar Jan Gerber
Browse files

* 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

parent c0288b1a
......@@ -216,6 +216,9 @@ Set niceness to n.
.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)
......
......@@ -16,11 +16,14 @@ options="$common --enable-pthreads $extra"
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
......
/* -*- 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@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);
}
}
*/
#ifndef _F2T_AVINFO_H_
#define _F2T_AVINFO_H_
void json_format_info(FILE* output, AVFormatContext *ic, const char *url);
#endif
......@@ -47,6 +47,7 @@
#include "iso639.h"
#include "subtitles.h"
#include "ffmpeg2theora.h"
#include "avinfo.h"
enum {
NULL_FLAG,
......@@ -75,7 +76,8 @@ enum {
FRONTENDFILE_FLAG,
SPEEDLEVEL_FLAG,
PP_FLAG,
NOSKELETON
NOSKELETON,
INFO_FLAG
} F2T_FLAGS;
enum {
......@@ -746,8 +748,6 @@ void ff2theora_output(ff2theora this) {
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 @@ void ff2theora_output(ff2theora this) {
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 @@ void ff2theora_output(ff2theora this) {
}
/* 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 @@ void print_usage() {
" --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,6 +1583,8 @@ void print_usage() {
#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"
......@@ -1623,6 +1618,7 @@ int main(int argc, char **argv) {
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 @@ int main(int argc, char **argv) {
{"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 @@ int main(int argc, char **argv) {
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 @@ int main(int argc, char **argv) {
}
}
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 @@ int main(int argc, char **argv) {
}
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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment