convert.cc revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <Audio.h>
#include <AudioFile.h>
#include <AudioPipe.h>
#include <AudioRawPipe.h>
#include <AudioLib.h>
#include <AudioTypePcm.h>
#include <AudioTypeG72X.h>
#include <AudioTypeChannel.h>
#include <AudioTypeMux.h>
#include <AudioTypeSampleRate.h>
#include <convert.h>
// Maximum sizes of buffer to convert, in seconds and bytes
#define CVTMAXTIME ((double)5.0)
// maintain a list of conversions
struct conv_list {
unsigned bufcnt; // number of buffers to process
char *desc; // describe conversion (for errs)
};
// check if this is a valid conversion. return -1 if not, 0 if OK.
int
{
char *enc1;
char *enc2;
delete enc1;
delete enc2;
return (-1);
}
return (0);
}
// check if this conversion is a no-op
int
off_t /* o_offset */)
{
(i_offset == 0)) {
return (1);
}
return (0);
}
// Conversion list maintenance routines
// Return a pointer to the last conversion entry in the list
struct conv_list
{
break;
}
return (lp);
}
// Release the conversion list
void
{
unsigned int i;
unsigned int bufs;
for (i = 0; i < bufs; i++) {
// Delete the conversion string
// Delete the conversion class if unique
}
}
}
// Append a new entry on the end of the conversion list
void
unsigned int bufs, // number of buffers involved
char *desc) // string describing the transform
{
unsigned int i;
Boolean B;
exit(1);
}
// Initialize a conversion entry for each expected buffer
for (i = 0; i < bufs; i++) {
} else {
}
}
// Link in the new entry
} else {
}
}
// Routines to establish specific conversions.
// These routines append the proper conversion to the list, and update
// the audio header structure to reflect the resulting data format.
// Multiplex/Demultiplex interleaved data
// If the data is multi-channel, demultiplex into multiple buffer streams.
// If there are multiple buffers, multiplex back into one interleaved stream.
unsigned int& bufs)
{
unsigned int n;
char *msg;
conv = new AudioTypeMux;
// Verify conversion
return (AUDIO_ERR_FORMATLOCK);
}
if (bufs == 1) {
// Demultiplex multi-channel data
} else {
// Multiplex multiple buffers
n = 1;
}
goto error;
bufs = n;
return (AUDIO_SUCCESS);
}
// Convert to PCM (linear, ulaw, alaw)
unsigned int unitsz,
unsigned int& bufs)
{
char *infmt;
char *outfmt;
conv = new AudioTypePcm;
// Verify conversion
return (AUDIO_ERR_FORMATLOCK);
}
// Set up conversion, get encoding strings
goto error;
delete infmt;
delete outfmt;
return (AUDIO_SUCCESS);
}
// Convert multi-channel data to mono, or vice versa
unsigned int tochans,
unsigned int& bufs)
{
char *inchans;
char *outchans;
return (AUDIO_ERR_FORMATLOCK);
conv = new AudioTypeChannel;
// Verify conversion; if no good, try converting to 16-bit pcm first
delete conv;
return (err);
}
return (AUDIO_ERR_FORMATLOCK);
}
}
// Set up conversion, get channel strings
goto error;
delete inchans;
delete outchans;
return (AUDIO_SUCCESS);
}
// Compress data
unsigned int unitsz,
unsigned int& bufs)
{
char *infmt;
char *outfmt;
int i;
// Make sure we're converting something we understand
return (AUDIO_ERR_FORMATLOCK);
conv = new AudioTypeG72X;
// Verify conversion; if no good, try converting to 16-bit pcm first
delete conv;
return (err);
}
return (AUDIO_ERR_FORMATLOCK);
}
}
// Set up conversion, get encoding strings
switch (tofmt) {
case G721:
break;
case G723:
break;
}
goto error;
delete infmt;
delete outfmt;
// Need a separate converter instantiation for each channel
for (i = 0; i < bufs; i++) {
if (i == 0)
else
}
return (AUDIO_SUCCESS);
}
// Decompress data
unsigned int unitsz,
unsigned int& bufs)
{
char *infmt;
char *outfmt;
int i;
// Make sure we're converting something we understand
return (AUDIO_ERR_FORMATLOCK);
conv = new AudioTypeG72X;
// Verify conversion
return (AUDIO_ERR_FORMATLOCK);
}
// Set up conversion, get encoding strings
// Try converting to 16-bit linear
goto error;
}
delete infmt;
delete outfmt;
// Need a separate converter instantiation for each channel
for (i = 0; i < bufs; i++) {
if (i == 0)
else
}
return (AUDIO_SUCCESS);
}
// Sample rate conversion
unsigned int torate,
unsigned int& bufs)
{
unsigned int fromrate;
char *inrate;
char *outrate;
int i;
// Verify conversion; if no good, try converting to 16-bit pcm first
delete conv;
return (err);
}
return (AUDIO_ERR_FORMATLOCK);
}
}
// Set up conversion, get encoding strings
goto error;
delete inrate;
delete outrate;
// Need a separate converter instantiation for each channel
for (i = 0; i < bufs; i++) {
if (i == 0)
else
}
return (AUDIO_SUCCESS);
}
// Returns TRUE if the specified header has a pcm type encoding
{
return (FALSE);
case LINEAR:
case FLOAT:
case ULAW:
case ALAW:
return (TRUE);
}
return (FALSE);
}
(ihp.samples_per_unit != \
ohp.samples_per_unit) || \
// Build the conversion list to get from input to output format
{
unsigned int bufs;
bufs = 1;
// Each pass, add another conversion, until there's no more to do
// First off, if the target is mono, convert the source to mono
// before doing harder stuff, like sample rate conversion.
// If multi-channel pcm,
// mix the channels down to one
} else {
// If not pcm, demultiplex in order
// to decompress
}
continue;
} else if (bufs != 1) {
// Multi-channel data was demultiplexed
// If multi-channel pcm, recombine them
// for mixing down to one
} else {
// If not pcm, decompress it
bufs);
}
continue;
}
// At this point, input and output are both mono
// Here if input and output are both multi-channel.
// If sample rate conversion or compression,
// split into multiple streams
continue;
}
}
// Input is either mono, split into multiple buffers, or
// this is a conversion that can be handled multi-channel.
// Decompress before sample-rate conversion
bufs);
} else {
}
continue;
}
// Encoding is changing:
// if we start compressed, decompress
bufs);
// we should be able to convert to PCM now
bufs);
} else {
// we should be able to compress now
bufs);
}
continue;
}
// The sample rate and encoding match.
// All that's left to do is get the channels right
if (bufs > 1) {
// Combine channels back into an interleaved stream
continue;
}
// If multi-channel output, try to accomodate
continue;
}
// Everything should be done at this point.
// XXX - this should never be reached
return (AUDIO_ERR_FORMATLOCK);
}
return (err);
}
// Set up the conversion list and execute it
int
{
unsigned int i;
char *msg1;
char *msg2;
// create conversion list
delete msg1;
return (-1);
}
// Print warnings for exceptional conditions
delete msg1;
}
delete msg1;
}
if (Debug) {
delete msg1;
delete msg2;
// Print each entry in the conversion list
}
}
// Calculate buffer size, obeying maximums
if (cvtlen > CVTMAXTIME)
cvtlen = CVTMAXTIME;
// create output buf
exit(1);
}
while (1) {
// Reset length
return (-1);
}
// If growing buffer, free the old one rather than copy data
// Read a chunk of input and set the real length of buffer
// XXX - Use Copy() method?? Check for errors?
break;
// Process each entry in the conversion list
// If multiple buffers, make multiple calls
} else {
if (err)
break;
}
}
if (err) {
"Conversion failed: %s (%s)\n"),
return (-1);
}
}
}
return (-1);
}
}
// First check if there's any residual to convert.
// If not, just set the header to this type.
// If multiple buffers, make multiple calls
if (!err)
} else {
if (!err) {
multibuf[i]);
}
if (err)
break;
}
}
if (err) {
"Warning: Flush of final bytes failed: "
"%s (%s)\n"),
/* return (-1); ignore errors for now */
break;
}
}
}
/* return (-1); ignore errors for now */
}
}
delete obuf;
return (0);
}