ref: c03429abf70d7d4b78ef3e1f2a1707d16b9d8e6a
parent: 1d5431d2d8a19e1f733799598a235c8573bb3c1d
author: Mark Harris <[email protected]>
date: Wed Feb 21 17:05:59 EST 2018
opusenc: Improve error reporting Check the return code of every libopusenc function and display an error when appropriate.
--- a/src/opusenc.c
+++ b/src/opusenc.c
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)
# include <unistd.h>
# include <time.h>
@@ -92,18 +93,35 @@
#define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */
-void opustoolsversion(const char *opusversion)
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+# define FORMAT_PRINTF __attribute__((__format__(printf, 1, 2)))
+#else
+# define FORMAT_PRINTF
+#endif
+
+static void fatal(const char *format, ...) FORMAT_PRINTF;
+
+static void fatal(const char *format, ...)
{
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ exit(1);
+}
+
+static void opustoolsversion(const char *opusversion)
+{
printf("opusenc %s %s (using %s)\n",PACKAGE_NAME,PACKAGE_VERSION,opusversion);
printf("Copyright (C) 2008-2017 Xiph.Org Foundation\n");
}
-void opustoolsversion_short(const char *opusversion)
+static void opustoolsversion_short(const char *opusversion)
{
opustoolsversion(opusversion);
}
-void usage(void)
+static void usage(void)
{
printf("Usage: opusenc [options] input_file output_file.opus\n");
printf("\n");
@@ -132,7 +150,7 @@
printf(" --comp n Set encoding complexity (0-10, default: 10 (slowest))\n");
printf(" --framesize n Set maximum frame size in milliseconds\n");
printf(" (2.5, 5, 10, 20, 40, 60, default: 20)\n");
- printf(" --expect-loss Set expected packet loss in percent (default: 0)\n");
+ printf(" --expect-loss n Set expected packet loss in percent (default: 0)\n");
printf(" --downmix-mono Downmix to mono\n");
printf(" --downmix-stereo Downmix to stereo (if >2 channels)\n");
printf(" --max-delay n Set maximum container delay in milliseconds\n");
@@ -165,7 +183,7 @@
printf(" This may be used multiple times\n");
}
-void help_picture(void)
+static void help_picture(void)
{
printf(" The --picture option can be used with a FILENAME, naming a JPEG,\n");
printf(" PNG, or GIF image file, or a more complete SPECIFICATION. The\n");
@@ -241,7 +259,8 @@
FILE *frange;
} EncData;
-int write_callback(void *user_data, const unsigned char *ptr, opus_int32 len) {
+static int write_callback(void *user_data, const unsigned char *ptr, opus_int32 len)
+{
EncData *data = (EncData*)user_data;
data->bytes_written += len;
data->pages_out++;
@@ -248,17 +267,17 @@
return fwrite(ptr, 1, len, data->fout) != (size_t)len;
}
-int close_callback(void *user_data) {
+static int close_callback(void *user_data)
+{
EncData *obj = (EncData*)user_data;
- int ret = 0;
- if (obj->fout) ret = fclose(obj->fout);
- return ret;
+ return fclose(obj->fout) != 0;
}
-int packet_callback(void *user_data, const unsigned char *packet_ptr, opus_int32 packet_len, opus_uint32 flags) {
+static void packet_callback(void *user_data, const unsigned char *packet_ptr, opus_int32 packet_len, opus_uint32 flags)
+{
EncData *data = (EncData*)user_data;
int nb_samples = opus_packet_get_nb_samples(packet_ptr, packet_len, 48000);
- if (nb_samples <= 0) return 0; /* ignore header packets */
+ if (nb_samples <= 0) return; /* ignore header packets */
data->total_bytes+=packet_len;
data->peak_bytes=IMAX(packet_len,data->peak_bytes);
data->min_bytes=IMIN(packet_len,data->min_bytes);
@@ -272,20 +291,19 @@
int nb_streams;
for(nb_streams=0;;nb_streams++){
ret=ope_encoder_ctl(data->enc,OPUS_MULTISTREAM_GET_ENCODER_STATE(nb_streams,&oe));
- if (ret != 0 || oe == NULL) break;
+ if (ret != OPE_OK || oe == NULL) break;
ret=opus_encoder_ctl(oe,OPUS_GET_FINAL_RANGE(&rngs[nb_streams]));
+ if (ret != OPE_OK) break;
}
save_range(data->frange,nb_samples,packet_ptr,packet_len,
rngs,nb_streams);
}
(void)flags;
- return 0;
}
int main(int argc, char **argv)
{
static const input_format raw_format = {NULL, 0, raw_open, wav_close, "raw",N_("RAW file reader")};
- int option_index=0;
struct option long_options[] =
{
{"quiet", no_argument, NULL, 0},
@@ -312,7 +330,6 @@
{"raw-chan", required_argument, NULL, 0},
{"raw-endianness", required_argument, NULL, 0},
{"ignorelength", no_argument, NULL, 0},
- {"rate", required_argument, NULL, 0},
{"version", no_argument, NULL, 0},
{"version-short", no_argument, NULL, 0},
{"comment", required_argument, NULL, 0},
@@ -406,11 +423,15 @@
serialno=rand();
inopt.comments = ope_comments_create();
+ if (inopt.comments == NULL) fatal("Error: failed to allocate memory for comments\n");
opus_version=opus_get_version_string();
/*Vendor string should just be the encoder library,
the ENCODER comment specifies the tool used.*/
snprintf(ENCODER_string, sizeof(ENCODER_string), "opusenc from %s %s",PACKAGE_NAME,PACKAGE_VERSION);
- ope_comments_add(inopt.comments, "ENCODER", ENCODER_string);
+ ret = ope_comments_add(inopt.comments, "ENCODER", ENCODER_string);
+ if (ret != OPE_OK) {
+ fatal("Error: failed to add ENCODER comment: %s\n", ope_strerror(ret));
+ }
/*Process command-line options*/
cline_size=0;
@@ -417,89 +438,90 @@
data.frange = NULL;
while(1){
int c;
- int save_cmd=1;
- c=getopt_long(argc_utf8, argv_utf8, "hV",
- long_options, &option_index);
+ int save_cmd;
+ int option_index;
+ const char *optname;
+
+ c=getopt_long(argc_utf8, argv_utf8, "hV", long_options, &option_index);
if(c==-1)
break;
switch(c){
case 0:
- if(strcmp(long_options[option_index].name,"quiet")==0){
+ optname = long_options[option_index].name;
+ save_cmd = 1;
+ if (strcmp(optname, "quiet")==0) {
quiet=1;
save_cmd=0;
- }else if(strcmp(long_options[option_index].name,"bitrate")==0){
+ } else if (strcmp(optname, "bitrate")==0) {
bitrate=atof(optarg)*1000.;
- }else if(strcmp(long_options[option_index].name,"hard-cbr")==0){
+ } else if (strcmp(optname, "hard-cbr")==0) {
with_hard_cbr=1;
with_cvbr=0;
- }else if(strcmp(long_options[option_index].name,"cvbr")==0){
+ } else if (strcmp(optname, "cvbr")==0) {
with_cvbr=1;
with_hard_cbr=0;
- }else if(strcmp(long_options[option_index].name,"vbr")==0){
+ } else if (strcmp(optname, "vbr")==0) {
with_cvbr=0;
with_hard_cbr=0;
- }else if(strcmp(long_options[option_index].name,"help")==0){
+ } else if (strcmp(optname, "help")==0) {
usage();
exit(0);
- }else if(strcmp(long_options[option_index].name,"help-picture")==0){
+ } else if (strcmp(optname, "help-picture")==0) {
help_picture();
exit(0);
- }else if(strcmp(long_options[option_index].name,"version")==0){
+ } else if (strcmp(optname, "version")==0) {
opustoolsversion(opus_version);
exit(0);
- }else if(strcmp(long_options[option_index].name,"version-short")==0){
+ } else if (strcmp(optname, "version-short")==0) {
opustoolsversion_short(opus_version);
exit(0);
- }else if(strcmp(long_options[option_index].name,"ignorelength")==0){
+ } else if (strcmp(optname, "ignorelength")==0) {
inopt.ignorelength=1;
save_cmd=0;
- }else if(strcmp(long_options[option_index].name,"raw")==0){
+ } else if (strcmp(optname, "raw")==0) {
inopt.rawmode=1;
save_cmd=0;
- }else if(strcmp(long_options[option_index].name,"raw-bits")==0){
+ } else if (strcmp(optname, "raw-bits")==0) {
inopt.rawmode=1;
inopt.samplesize=atoi(optarg);
save_cmd=0;
if(inopt.samplesize!=8&&inopt.samplesize!=16&&inopt.samplesize!=24){
- fprintf(stderr,"Invalid bit-depth: %s\n",optarg);
- fprintf(stderr,"--raw-bits must be one of 8,16, or 24\n");
- exit(1);
+ fatal("Invalid bit-depth: %s\n"
+ "--raw-bits must be one of 8, 16, or 24\n", optarg);
}
- }else if(strcmp(long_options[option_index].name,"raw-rate")==0){
+ } else if (strcmp(optname, "raw-rate")==0) {
inopt.rawmode=1;
inopt.rate=atoi(optarg);
save_cmd=0;
- }else if(strcmp(long_options[option_index].name,"raw-chan")==0){
+ } else if (strcmp(optname, "raw-chan")==0) {
inopt.rawmode=1;
inopt.channels=atoi(optarg);
save_cmd=0;
- }else if(strcmp(long_options[option_index].name,"raw-endianness")==0){
+ } else if (strcmp(optname, "raw-endianness")==0) {
inopt.rawmode=1;
inopt.endianness=atoi(optarg);
save_cmd=0;
- }else if(strcmp(long_options[option_index].name,"downmix-mono")==0){
+ } else if (strcmp(optname, "downmix-mono")==0) {
downmix=1;
- }else if(strcmp(long_options[option_index].name,"downmix-stereo")==0){
+ } else if (strcmp(optname, "downmix-stereo")==0) {
downmix=2;
- }else if(strcmp(long_options[option_index].name,"no-downmix")==0){
+ } else if (strcmp(optname, "no-downmix")==0) {
downmix=-1;
- }else if(strcmp(long_options[option_index].name,"expect-loss")==0){
+ } else if (strcmp(optname, "expect-loss")==0) {
expect_loss=atoi(optarg);
if(expect_loss>100||expect_loss<0){
- fprintf(stderr,"Invalid expect-loss: %s\n",optarg);
- fprintf(stderr,"Expected loss is a percent and must be 0-100.\n");
- exit(1);
+ fatal("Invalid expect-loss: %s\n"
+ "Expected loss is a percentage in the range 0 to 100.\n", optarg);
}
- }else if(strcmp(long_options[option_index].name,"comp")==0 ||
- strcmp(long_options[option_index].name,"complexity")==0){
+ } else if (strcmp(optname, "comp")==0 ||
+ strcmp(optname, "complexity")==0) {
complexity=atoi(optarg);
if(complexity>10||complexity<0){
- fprintf(stderr,"Invalid complexity: %s\n",optarg);
- fprintf(stderr,"Complexity must be 0-10.\n");
- exit(1);
+ fatal("Invalid complexity: %s\n"
+ "Complexity must be in the range 0 to 10.\n", optarg);
}
- }else if(strcmp(long_options[option_index].name,"framesize")==0){
+ } else if (strcmp(optname, "framesize")==0) {
if(strcmp(optarg,"2.5")==0)opus_frame_param=OPUS_FRAMESIZE_2_5_MS;
else if(strcmp(optarg,"5")==0)opus_frame_param=OPUS_FRAMESIZE_5_MS;
else if(strcmp(optarg,"10")==0)opus_frame_param=OPUS_FRAMESIZE_10_MS;
@@ -507,40 +529,30 @@
else if(strcmp(optarg,"40")==0)opus_frame_param=OPUS_FRAMESIZE_40_MS;
else if(strcmp(optarg,"60")==0)opus_frame_param=OPUS_FRAMESIZE_60_MS;
else{
- fprintf(stderr,"Invalid framesize: %s\n",optarg);
- fprintf(stderr,"Framesize must be 2.5, 5, 10, 20, 40, or 60.\n");
- exit(1);
+ fatal("Invalid framesize: %s\n"
+ "Value is in milliseconds and must be 2.5, 5, 10, 20, 40, or 60.\n",
+ optarg);
}
-
- if(strcmp(optarg,"2.5")==0)frame_size=120;
- else if(strcmp(optarg,"5")==0)frame_size=240;
- else if(strcmp(optarg,"10")==0)frame_size=480;
- else if(strcmp(optarg,"20")==0)frame_size=960;
- else if(strcmp(optarg,"40")==0)frame_size=1920;
- else if(strcmp(optarg,"60")==0)frame_size=2880;
- else{
- fprintf(stderr,"Invalid framesize: %s\n",optarg);
- fprintf(stderr,"Framesize must be 2.5, 5, 10, 20, 40, or 60.\n");
- exit(1);
- }
- }else if(strcmp(long_options[option_index].name,"max-delay")==0){
+ frame_size = opus_frame_param <= OPUS_FRAMESIZE_40_MS
+ ? 120 << (opus_frame_param - OPUS_FRAMESIZE_2_5_MS)
+ : (opus_frame_param - OPUS_FRAMESIZE_20_MS + 1) * 960;
+ } else if (strcmp(optname, "max-delay")==0) {
max_ogg_delay=floor(atof(optarg)*48.);
if(max_ogg_delay<0||max_ogg_delay>48000){
- fprintf(stderr,"Invalid max-delay: %s\n",optarg);
- fprintf(stderr,"max-delay 0-1000 ms.\n");
- exit(1);
+ fatal("Invalid max-delay: %s\n"
+ "Value is in milliseconds and must be in the range 0 to 1000.\n",
+ optarg);
}
- }else if(strcmp(long_options[option_index].name,"serial")==0){
+ } else if (strcmp(optname, "serial")==0) {
serialno=atoi(optarg);
- }else if(strcmp(long_options[option_index].name,"set-ctl-int")==0){
- int len=strlen(optarg),target;
+ } else if (strcmp(optname, "set-ctl-int")==0) {
+ int len=strlen(optarg),target,request;
char *spos,*tpos;
spos=strchr(optarg,'=');
if(len<3||spos==NULL||(spos-optarg)<1||(spos-optarg)>=len){
- fprintf(stderr, "Invalid set-ctl-int: %s\n", optarg);
- fprintf(stderr, "Syntax is --set-ctl-int intX=intY or\n");
- fprintf(stderr, "Syntax is --set-ctl-int intS:intX=intY\n");
- exit(1);
+ fatal("Invalid set-ctl-int: %s\n"
+ "Syntax is --set-ctl-int intX=intY\n"
+ " or --set-ctl-int intS:intX=intY\n", optarg);
}
tpos=strchr(optarg,':');
if(tpos==NULL){
@@ -547,56 +559,48 @@
target=-1;
tpos=optarg-1;
}else target=atoi(optarg);
- if((atoi(tpos+1)&1)!=0){
- fprintf(stderr, "Invalid set-ctl-int: %s\n", optarg);
- fprintf(stderr, "libopus set CTL values are even.\n");
- exit(1);
+ request=atoi(tpos+1);
+ if ((request & 1) != 0 || request == OPE_SET_PACKET_CALLBACK_REQUEST) {
+ fatal("Invalid set-ctl-int: %s\n"
+ "Set ctl values are even.\n", optarg);
}
if(opt_ctls==0)opt_ctls_ctlval=malloc(sizeof(int)*3);
else opt_ctls_ctlval=realloc(opt_ctls_ctlval,sizeof(int)*(opt_ctls+1)*3);
- if(!opt_ctls_ctlval)
- {
- fprintf(stderr, "Memory allocation failure.\n");
- exit(1);
- }
+ if (!opt_ctls_ctlval) fatal("Error: failed to allocate memory for ctls\n");
opt_ctls_ctlval[opt_ctls*3]=target;
- opt_ctls_ctlval[opt_ctls*3+1]=atoi(tpos+1);
+ opt_ctls_ctlval[opt_ctls*3+1]=request;
opt_ctls_ctlval[opt_ctls*3+2]=atoi(spos+1);
opt_ctls++;
- }else if(strcmp(long_options[option_index].name,"save-range")==0){
+ } else if (strcmp(optname, "save-range")==0) {
data.frange=fopen_utf8(optarg,"w");
save_cmd=0;
if(data.frange==NULL){
perror(optarg);
- fprintf(stderr,"Could not open save-range file: %s\n",optarg);
- fprintf(stderr,"Must provide a writable file name.\n");
- exit(1);
+ fatal("Error: cannot open save-range file: %s\n"
+ "Must provide a writable file name.\n", optarg);
}
range_file=optarg;
- }else if(strcmp(long_options[option_index].name,"comment")==0){
+ } else if (strcmp(optname, "comment")==0) {
save_cmd=0;
if(!strchr(optarg,'=')){
- fprintf(stderr, "Invalid comment: %s\n", optarg);
- fprintf(stderr, "Comments must be of the form name=value\n");
- exit(1);
+ fatal("Invalid comment: %s\n"
+ "Comments must be of the form name=value\n", optarg);
}
- ope_comments_add_string(inopt.comments, optarg);
- }else if(strcmp(long_options[option_index].name,"artist")==0){
+ ret = ope_comments_add_string(inopt.comments, optarg);
+ if (ret != OPE_OK) {
+ fatal("Error: failed to add comment: %s\n", ope_strerror(ret));
+ }
+ } else if (strcmp(optname, "artist") == 0 ||
+ strcmp(optname, "title") == 0 ||
+ strcmp(optname, "album") == 0 ||
+ strcmp(optname, "date") == 0 ||
+ strcmp(optname, "genre") == 0) {
save_cmd=0;
- ope_comments_add(inopt.comments, "artist", optarg);
- } else if(strcmp(long_options[option_index].name,"title")==0){
- save_cmd=0;
- ope_comments_add(inopt.comments, "title", optarg);
- } else if(strcmp(long_options[option_index].name,"album")==0){
- save_cmd=0;
- ope_comments_add(inopt.comments, "album", optarg);
- } else if(strcmp(long_options[option_index].name,"date")==0){
- save_cmd=0;
- ope_comments_add(inopt.comments, "date", optarg);
- } else if(strcmp(long_options[option_index].name,"genre")==0){
- save_cmd=0;
- ope_comments_add(inopt.comments, "genre", optarg);
- } else if(strcmp(long_options[option_index].name,"picture")==0){
+ ret = ope_comments_add(inopt.comments, optname, optarg);
+ if (ret != OPE_OK) {
+ fatal("Error: failed to add %s comment: %s\n", optname, ope_strerror(ret));
+ }
+ } else if (strcmp(optname, "picture")==0) {
const char *media_type;
const char *media_type_end;
const char *description;
@@ -620,12 +624,12 @@
the full form of the specification.*/
val=strtoul(spec,&q,10);
if(*q!='|'||val>20){
- fprintf(stderr, "Invalid picture type: %.*s\n",
+ fatal("Invalid picture type: %.*s\n"
+ "Picture type must be in the range 0 to 20; see --help-picture.\n",
(int)strcspn(spec,"|"), spec);
- exit(1);
}
/*An empty field implies a default of 'Cover (front)'.*/
- if(spec!=q)picture_type=val;
+ if(spec!=q)picture_type=(int)val;
media_type=q+1;
media_type_end=media_type+strcspn(media_type,"|");
if(*media_type_end=='|'){
@@ -641,17 +645,18 @@
}
}
if (filename==spec) {
- fprintf(stderr, "Not enough fields in picture specification: %s\n", spec);
- exit(1);
+ fatal("Not enough fields in picture specification:\n %s\n"
+ "The format of a picture specification is:\n"
+ " [TYPE]|[MEDIA-TYPE]|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]"
+ "|FILENAME\nSee --help-picture.\n", spec);
}
if (media_type_end-media_type==3 && strncmp("-->",media_type,3)==0) {
- fprintf(stderr, "Picture URLs are no longer supported.\n");
- exit(1);
+ fatal("Picture URLs are no longer supported.\n"
+ "See --help-picture.\n");
}
if (picture_type>=1&&picture_type<=2&&(seen_file_icons&picture_type)) {
- fprintf(stderr, "Only one picture of type %d (%s) is allowed.\n",
+ fatal("Error: only one picture of type %d (%s) is allowed\n",
picture_type, picture_type==1 ? "32x32 icon" : "icon");
- exit(1);
}
}
if (picture_file) fclose(picture_file);
@@ -661,19 +666,19 @@
memcpy(description_copy, description, len);
description_copy[len]=0;
}
- ret = ope_comments_add_picture(inopt.comments, filename, picture_type, description_copy);
+ ret = ope_comments_add_picture(inopt.comments, filename,
+ picture_type, description_copy);
if (ret != OPE_OK) {
- fprintf(stderr, "Error: %s: %s\n", ope_strerror(ret), filename);
- exit(1);
+ fatal("Error: %s: %s\n", ope_strerror(ret), filename);
}
if (description_copy) free(description_copy);
if (picture_type>=1&&picture_type<=2) seen_file_icons|=picture_type;
- } else if(strcmp(long_options[option_index].name,"padding")==0){
+ } else if (strcmp(optname, "padding")==0) {
comment_padding=atoi(optarg);
- } else if(strcmp(long_options[option_index].name,"discard-comments")==0){
+ } else if (strcmp(optname, "discard-comments")==0) {
inopt.copy_comments=0;
inopt.copy_pictures=0;
- } else if(strcmp(long_options[option_index].name,"discard-pictures")==0){
+ } else if (strcmp(optname, "discard-pictures")==0) {
inopt.copy_pictures=0;
}
/*Options whose arguments would leak file paths or just end up as
@@ -680,6 +685,24 @@
metadata, or that relate only to input file handling or console
output, should have save_cmd=0; to prevent them from being saved
in the ENCODER_OPTIONS tag.*/
+ if (save_cmd && cline_size<(int)sizeof(ENCODER_string)) {
+ ret=snprintf(&ENCODER_string[cline_size], sizeof(ENCODER_string)-cline_size,
+ "%s--%s", cline_size==0?"":" ", optname);
+ if(ret<0||ret>=((int)sizeof(ENCODER_string)-cline_size)){
+ cline_size=sizeof(ENCODER_string);
+ } else {
+ cline_size+=ret;
+ if(optarg){
+ ret=snprintf(&ENCODER_string[cline_size],
+ sizeof(ENCODER_string)-cline_size, " %s",optarg);
+ if(ret<0||ret>=((int)sizeof(ENCODER_string)-cline_size)){
+ cline_size=sizeof(ENCODER_string);
+ } else {
+ cline_size+=ret;
+ }
+ }
+ }
+ }
break;
case 'h':
usage();
@@ -694,22 +717,6 @@
exit(1);
break;
}
- if(save_cmd && cline_size<(int)sizeof(ENCODER_string)){
- ret=snprintf(&ENCODER_string[cline_size], sizeof(ENCODER_string)-cline_size, "%s--%s",cline_size==0?"":" ",long_options[option_index].name);
- if(ret<0||ret>=((int)sizeof(ENCODER_string)-cline_size)){
- cline_size=sizeof(ENCODER_string);
- } else {
- cline_size+=ret;
- if(optarg){
- ret=snprintf(&ENCODER_string[cline_size], sizeof(ENCODER_string)-cline_size, " %s",optarg);
- if(ret<0||ret>=((int)sizeof(ENCODER_string)-cline_size)){
- cline_size=sizeof(ENCODER_string);
- } else {
- cline_size+=ret;
- }
- }
- }
- }
}
if(argc_utf8-optind!=2){
usage();
@@ -718,7 +725,12 @@
inFile=argv_utf8[optind];
outFile=argv_utf8[optind+1];
- if(cline_size>0)ope_comments_add(inopt.comments, "ENCODER_OPTIONS", ENCODER_string);
+ if (cline_size > 0) {
+ ret = ope_comments_add(inopt.comments, "ENCODER_OPTIONS", ENCODER_string);
+ if (ret != OPE_OK) {
+ fatal("Error: failed to add ENCODER_OPTIONS comment: %s\n", ope_strerror(ret));
+ }
+ }
if(strcmp(inFile, "-")==0){
#if defined WIN32 || defined _WIN32
@@ -741,19 +753,17 @@
}else in_format=open_audio_file(fin,&inopt);
if(!in_format){
- fprintf(stderr,"Error parsing input file: %s\n",inFile);
- exit(1);
+ fatal("Error: unsupported input file: %s\n", inFile);
}
if(inopt.rate<100||inopt.rate>768000){
/*Crazy rates excluded to avoid excessive memory usage for padding/resampling.*/
- fprintf(stderr,"Error parsing input file: %s unhandled sampling rate: %ld Hz\n",inFile,inopt.rate);
- exit(1);
+ fatal("Error: unsupported sample rate in input file: %ld Hz\n", inopt.rate);
}
if(inopt.channels>255||inopt.channels<1){
- fprintf(stderr,"Error parsing input file: %s unhandled number of channels: %d\n",inFile,inopt.channels);
- exit(1);
+ fatal("Error: unsupported channel count in input file: %d\n"
+ "Channel count must be in the range 1 to 255.\n", inopt.channels);
}
if(downmix==0&&inopt.channels>2&&bitrate>0&&bitrate<(16000*inopt.channels)){
@@ -772,17 +782,39 @@
((double)inopt.total_samples_per_channel * (48000./(double)rate));
/*Initialize Opus encoder*/
- enc = ope_encoder_create_callbacks(&callbacks, &data, inopt.comments, rate, chan, chan>8?255:chan>2, NULL);
- ope_encoder_ctl(enc, OPE_SET_MUXING_DELAY(max_ogg_delay));
- ope_encoder_ctl(enc, OPE_SET_SERIALNO(serialno));
- ope_encoder_ctl(enc, OPE_SET_HEADER_GAIN(inopt.gain));
- ope_encoder_ctl(enc, OPE_SET_PACKET_CALLBACK(packet_callback, &data));
- ope_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(opus_frame_param));
- ope_encoder_ctl(enc, OPE_SET_COMMENT_PADDING(comment_padding));
+ enc = ope_encoder_create_callbacks(&callbacks, &data, inopt.comments, rate,
+ chan, chan>8?255:chan>2, &ret);
+ if (enc == NULL) fatal("Error: failed to create encoder: %s\n", ope_strerror(ret));
+
+ ret = ope_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(opus_frame_param));
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_SET_EXPERT_FRAME_DURATION failed: %s\n", ope_strerror(ret));
+ }
+ ret = ope_encoder_ctl(enc, OPE_SET_MUXING_DELAY(max_ogg_delay));
+ if (ret != OPE_OK) {
+ fatal("Error: OPE_SET_MUXING_DELAY failed: %s\n", ope_strerror(ret));
+ }
+ ret = ope_encoder_ctl(enc, OPE_SET_SERIALNO(serialno));
+ if (ret != OPE_OK) {
+ fatal("Error: OPE_SET_SERIALNO failed: %s\n", ope_strerror(ret));
+ }
+ ret = ope_encoder_ctl(enc, OPE_SET_HEADER_GAIN(inopt.gain));
+ if (ret != OPE_OK) {
+ fatal("Error: OPE_SET_HEADER_GAIN failed: %s\n", ope_strerror(ret));
+ }
+ ret = ope_encoder_ctl(enc, OPE_SET_PACKET_CALLBACK(packet_callback, &data));
+ if (ret != OPE_OK) {
+ fatal("Error: OPE_SET_PACKET_CALLBACK failed: %s\n", ope_strerror(ret));
+ }
+ ret = ope_encoder_ctl(enc, OPE_SET_COMMENT_PADDING(comment_padding));
+ if (ret != OPE_OK) {
+ fatal("Error: OPE_SET_COMMENT_PADDING failed: %s\n", ope_strerror(ret));
+ }
+
for(nb_streams=0;;nb_streams++){
OpusEncoder *oe;
ret=ope_encoder_ctl(enc,OPUS_MULTISTREAM_GET_ENCODER_STATE(nb_streams,&oe));
- if (ret != 0 || oe == NULL) break;
+ if (ret != OPE_OK || oe == NULL) break;
}
nb_coupled = chan - nb_streams;
@@ -793,89 +825,84 @@
}
if(bitrate>(1024000*chan)||bitrate<500){
- fprintf(stderr,"Error: Bitrate %d bits/sec is insane.\nDid you mistake bits for kilobits?\n",bitrate);
- fprintf(stderr,"--bitrate values from 6-256 kbit/sec per channel are meaningful.\n");
- exit(1);
+ fatal("Error: bitrate %d bits/sec is insane\n%s"
+ "--bitrate values from 6 to 256 kbit/sec per channel are meaningful.\n",
+ bitrate, bitrate>=1000000 ? "Did you mistake bits for kilobits?\n" : "");
}
bitrate=IMIN(chan*256000,bitrate);
ret = ope_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
- if(ret!=OPUS_OK){
- fprintf(stderr,"Error OPUS_SET_BITRATE returned: %s\n",opus_strerror(ret));
- exit(1);
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_SET_BITRATE %d failed: %s\n", bitrate, ope_strerror(ret));
}
-
ret = ope_encoder_ctl(enc, OPUS_SET_VBR(!with_hard_cbr));
- if(ret!=OPUS_OK){
- fprintf(stderr,"Error OPUS_SET_VBR returned: %s\n",opus_strerror(ret));
- exit(1);
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_SET_VBR %d failed: %s\n", !with_hard_cbr, ope_strerror(ret));
}
-
if(!with_hard_cbr){
ret = ope_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(with_cvbr));
- if(ret!=OPUS_OK){
- fprintf(stderr,"Error OPUS_SET_VBR_CONSTRAINT returned: %s\n",opus_strerror(ret));
- exit(1);
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_SET_VBR_CONSTRAINT %d failed: %s\n",
+ with_cvbr, ope_strerror(ret));
}
}
-
ret = ope_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
- if(ret!=OPUS_OK){
- fprintf(stderr,"Error OPUS_SET_COMPLEXITY returned: %s\n",opus_strerror(ret));
- exit(1);
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_SET_COMPLEXITY %d failed: %s\n", complexity, ope_strerror(ret));
}
-
ret = ope_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(expect_loss));
- if(ret!=OPUS_OK){
- fprintf(stderr,"Error OPUS_SET_PACKET_LOSS_PERC returned: %s\n",opus_strerror(ret));
- exit(1);
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_SET_PACKET_LOSS_PERC %d failed: %s\n",
+ expect_loss, ope_strerror(ret));
}
-
#ifdef OPUS_SET_LSB_DEPTH
ret = ope_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(IMAX(8,IMIN(24,inopt.samplesize))));
- if(ret!=OPUS_OK){
- fprintf(stderr,"Warning OPUS_SET_LSB_DEPTH returned: %s\n",opus_strerror(ret));
+ if (ret != OPE_OK) {
+ fprintf(stderr, "Warning: OPUS_SET_LSB_DEPTH failed: %s\n", ope_strerror(ret));
}
#endif
- /*This should be the last set of CTLs, except the lookahead get, so it can override the defaults.*/
+ /*This should be the last set of SET ctls, so it can override the defaults.*/
for(i=0;i<opt_ctls;i++){
int target=opt_ctls_ctlval[i*3];
if(target==-1){
ret = ope_encoder_ctl(enc, opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2]);
- if(ret!=OPUS_OK){
- fprintf(stderr,"Error opus_multistream_encoder_ctl(st,%d,%d) returned: %s\n",opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2],opus_strerror(ret));
- exit(1);
+ if (ret != OPE_OK) {
+ fatal("Error: failed to set encoder ctl %d=%d: %s\n",
+ opt_ctls_ctlval[i*3+1], opt_ctls_ctlval[i*3+2], ope_strerror(ret));
}
}else if(target<nb_streams){
OpusEncoder *oe;
- ope_encoder_ctl(enc, OPUS_MULTISTREAM_GET_ENCODER_STATE(target,&oe));
- ret=opus_encoder_ctl(oe, opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2]);
+ ret = ope_encoder_ctl(enc, OPUS_MULTISTREAM_GET_ENCODER_STATE(target,&oe));
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_MULTISTREAM_GET_ENCODER_STATE %d failed: %s\n",
+ target, ope_strerror(ret));
+ }
+ ret = opus_encoder_ctl(oe, opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2]);
if(ret!=OPUS_OK){
- fprintf(stderr,"Error opus_encoder_ctl(st[%d],%d,%d) returned: %s\n",target,opt_ctls_ctlval[i*3+1],opt_ctls_ctlval[i*3+2],opus_strerror(ret));
- exit(1);
+ fatal("Error: failed to set stream %d encoder ctl %d=%d: %s\n",
+ target, opt_ctls_ctlval[i*3+1], opt_ctls_ctlval[i*3+2], opus_strerror(ret));
}
}else{
- fprintf(stderr,"Error --set-ctl-int target stream %d is higher than the maximum stream number %d.\n",target,nb_streams-1);
- exit(1);
+ fatal("Error: --set-ctl-int stream %d is higher than the highest stream number %d\n",target,nb_streams-1);
}
}
- /*We do the lookahead check late so user CTLs can change it*/
+ /*We do the lookahead check late so user ctls can change it*/
ret = ope_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&lookahead));
- if(ret!=OPUS_OK){
- fprintf(stderr,"Error OPUS_GET_LOOKAHEAD returned: %s\n",opus_strerror(ret));
- exit(1);
+ if (ret != OPE_OK) {
+ fatal("Error: OPUS_GET_LOOKAHEAD failed: %s\n", ope_strerror(ret));
}
if(!quiet){
int opus_app;
fprintf(stderr,"Encoding using %s",opus_version);
- ope_encoder_ctl(enc, OPUS_GET_APPLICATION(&opus_app));
- if(opus_app==OPUS_APPLICATION_VOIP)fprintf(stderr," (VoIP)\n");
+ ret = ope_encoder_ctl(enc, OPUS_GET_APPLICATION(&opus_app));
+ if (ret != OPE_OK) fprintf(stderr, "\n");
+ else if(opus_app==OPUS_APPLICATION_VOIP)fprintf(stderr," (VoIP)\n");
else if(opus_app==OPUS_APPLICATION_AUDIO)fprintf(stderr," (audio)\n");
else if(opus_app==OPUS_APPLICATION_RESTRICTED_LOWDELAY)fprintf(stderr," (low-delay)\n");
- else fprintf(stderr," (unknown)\n");
+ else fprintf(stderr," (unknown application)\n");
fprintf(stderr,"-----------------------------------------------------\n");
fprintf(stderr," Input: %0.6gkHz %d channel%s\n",
rate/1000.,chan,chan<2?"":"s");
@@ -888,8 +915,9 @@
frame_size/(48000/1000.), bitrate/1000.,
with_hard_cbr?" CBR":with_cvbr?" CVBR":" VBR");
fprintf(stderr," Preskip: %d\n",lookahead);
-
- if(data.frange!=NULL)fprintf(stderr," Writing final range file %s\n",range_file);
+ if (data.frange!=NULL) {
+ fprintf(stderr, " Writing final range file %s\n", range_file);
+ }
fprintf(stderr,"\n");
}
@@ -917,8 +945,7 @@
input=malloc(sizeof(float)*frame_size*chan);
if(input==NULL){
- fprintf(stderr,"Error: couldn't allocate sample buffer.\n");
- exit(1);
+ fatal("Error: failed to allocate sample buffer\n");
}
/*Main encoding loop (one frame per iteration)*/
@@ -925,8 +952,8 @@
while(1){
nb_samples = inopt.read_samples(inopt.readdata,input,frame_size);
total_samples+=nb_samples;
- ope_encoder_write_float(enc, input, nb_samples);
- if (nb_samples < frame_size) break;
+ ret = ope_encoder_write_float(enc, input, nb_samples);
+ if (ret != OPE_OK || nb_samples < frame_size) break;
if(!quiet){
stop_time = time(NULL);
@@ -947,9 +974,11 @@
}
fprintf(stderr,"\r");
for(i=0;i<last_spin_len;i++)fprintf(stderr," ");
- if(inopt.total_samples_per_channel>0 && data.nb_encoded<inopt.total_samples_per_channel){
+ if (inopt.total_samples_per_channel>0 &&
+ data.nb_encoded<inopt.total_samples_per_channel+lookahead) {
snprintf(sbuf,54,"\r[%c] %2d%% ",spinner[last_spin&3],
- (int)floor(data.nb_encoded/(double)(inopt.total_samples_per_channel+lookahead)*100.));
+ (int)floor(data.nb_encoded
+ /(double)(inopt.total_samples_per_channel+lookahead)*100.));
}else{
snprintf(sbuf,54,"\r[%c] ",spinner[last_spin&3]);
}
@@ -968,13 +997,16 @@
}
}
- ope_encoder_drain(enc);
+ if (last_spin_len) {
+ fprintf(stderr,"\r");
+ for (i=0;i<last_spin_len;i++) fprintf(stderr," ");
+ fprintf(stderr,"\r");
+ }
+
+ if (ret == OPE_OK) ret = ope_encoder_drain(enc);
+ if (ret != OPE_OK) fatal("Encoding aborted: %s\n", ope_strerror(ret));
stop_time = time(NULL);
- if(last_spin_len)fprintf(stderr,"\r");
- for(i=0;i<last_spin_len;i++)fprintf(stderr," ");
- if(last_spin_len)fprintf(stderr,"\r");
-
if(!quiet){
double coded_seconds=data.nb_encoded/48000.;
double wall_time=(stop_time-start_time)+1e-6;
@@ -989,7 +1021,8 @@
if(data.nb_encoded>0){
fprintf(stderr," Bitrate: %0.6gkbit/s (without overhead)\n",
data.total_bytes*8.0/(coded_seconds)/1000.0);
- fprintf(stderr," Instant rates: %0.6gkbit/s to %0.6gkbit/s\n (%d to %d bytes per packet)\n",
+ fprintf(stderr," Instant rates: %0.6gkbit/s to %0.6gkbit/s\n"
+ " (%d to %d bytes per packet)\n",
data.min_bytes*(8*48000./frame_size/1000.),
data.peak_bytes*(8*48000./frame_size/1000.),data.min_bytes,data.peak_bytes);
}