mirror of https://github.com/FFmpeg/FFmpeg.git
Originally committed as revision 1934 to svn://svn.ffmpeg.org/ffmpeg/trunkpull/126/head
parent
14342fd537
commit
067cbf313f
1 changed files with 178 additions and 0 deletions
@ -0,0 +1,178 @@ |
|||||||
|
/*
|
||||||
|
* amr file format |
||||||
|
* Copyright (c) 2001 ffmpeg project |
||||||
|
* |
||||||
|
* This library is free software; you can redistribute it and/or |
||||||
|
* modify it under the terms of the GNU Lesser General Public |
||||||
|
* License as published by the Free Software Foundation; either |
||||||
|
* version 2 of the License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* This library 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 |
||||||
|
* Lesser General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU Lesser General Public |
||||||
|
* License along with this library; if not, write to the Free Software |
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267
|
||||||
|
|
||||||
|
Only amr narrowband (not amr-wb) is supported for now. |
||||||
|
|
||||||
|
*/ |
||||||
|
#include "avformat.h" |
||||||
|
#include "avi.h" |
||||||
|
|
||||||
|
static const unsigned char AMR_header [] = "#!AMR\n"; |
||||||
|
|
||||||
|
/* AMR_FILE header */ |
||||||
|
static int put_amr_header(ByteIOContext *pb, AVCodecContext *enc) |
||||||
|
{ |
||||||
|
put_tag(pb, AMR_header); /* magic number */ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int amr_write_header(AVFormatContext *s) |
||||||
|
{ |
||||||
|
ByteIOContext *pb = &s->pb; |
||||||
|
|
||||||
|
s->priv_data = NULL; |
||||||
|
|
||||||
|
/* format header */ |
||||||
|
if (put_amr_header(pb, &s->streams[0]->codec) < 0) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
put_flush_packet(pb); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int amr_write_packet(AVFormatContext *s, int stream_index_ptr, |
||||||
|
uint8_t *buf, int size, int force_pts) |
||||||
|
{ |
||||||
|
put_buffer(&s->pb, buf, size); |
||||||
|
put_flush_packet(&s->pb); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int amr_write_trailer(AVFormatContext *s) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int amr_probe(AVProbeData *p) |
||||||
|
{ |
||||||
|
/* check file header */ |
||||||
|
if (p->buf_size < 6) |
||||||
|
return 0; |
||||||
|
if(memcmp(p->buf,AMR_header,6)==0) |
||||||
|
return AVPROBE_SCORE_MAX; |
||||||
|
else |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/* amr input */ |
||||||
|
static int amr_read_header(AVFormatContext *s, |
||||||
|
AVFormatParameters *ap) |
||||||
|
{ |
||||||
|
ByteIOContext *pb = &s->pb; |
||||||
|
AVStream *st; |
||||||
|
u_int8_t header[6]; |
||||||
|
|
||||||
|
get_buffer(pb, header, 6); |
||||||
|
|
||||||
|
if(memcmp(header,AMR_header,6)!=0) |
||||||
|
{ |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
st = av_new_stream(s, 0); |
||||||
|
if (!st) |
||||||
|
return AVERROR_NOMEM; |
||||||
|
|
||||||
|
st->codec.codec_type = CODEC_TYPE_AUDIO; |
||||||
|
st->codec.codec_tag = CODEC_ID_AMR_NB; |
||||||
|
st->codec.codec_id = CODEC_ID_AMR_NB; |
||||||
|
st->codec.channels = 1; |
||||||
|
st->codec.sample_rate = 8000; |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
#define MAX_SIZE 32 |
||||||
|
|
||||||
|
static int amr_read_packet(AVFormatContext *s, |
||||||
|
AVPacket *pkt) |
||||||
|
{ |
||||||
|
static u_int16_t packed_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0}; |
||||||
|
u_int8_t toc, q, ft; |
||||||
|
int read; |
||||||
|
int size; |
||||||
|
|
||||||
|
if (url_feof(&s->pb)) |
||||||
|
return -EIO; |
||||||
|
|
||||||
|
toc=0; |
||||||
|
|
||||||
|
toc=get_byte(&s->pb); |
||||||
|
|
||||||
|
q = (toc >> 2) & 0x01; |
||||||
|
ft = (toc >> 3) & 0x0F; |
||||||
|
|
||||||
|
size=packed_size[ft]; |
||||||
|
//printf("amr_read_packet size=%d\n",size);
|
||||||
|
|
||||||
|
if (av_new_packet(pkt, size+1)) |
||||||
|
return -EIO; |
||||||
|
pkt->stream_index = 0; |
||||||
|
|
||||||
|
pkt->data[0]=toc; |
||||||
|
|
||||||
|
read = get_buffer(&s->pb, pkt->data+1, size); |
||||||
|
|
||||||
|
if (read != size) |
||||||
|
{ |
||||||
|
av_free_packet(pkt); |
||||||
|
return -EIO; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static int amr_read_close(AVFormatContext *s) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
static AVInputFormat amr_iformat = { |
||||||
|
"amr", |
||||||
|
"3gpp amr file format", |
||||||
|
0, |
||||||
|
amr_probe, |
||||||
|
amr_read_header, |
||||||
|
amr_read_packet, |
||||||
|
amr_read_close, |
||||||
|
}; |
||||||
|
|
||||||
|
static AVOutputFormat amr_oformat = { |
||||||
|
"amr", |
||||||
|
"3gpp amr file format", |
||||||
|
"audio/amr", |
||||||
|
"amr", |
||||||
|
0, |
||||||
|
CODEC_ID_AMR_NB, |
||||||
|
CODEC_ID_NONE, |
||||||
|
amr_write_header, |
||||||
|
amr_write_packet, |
||||||
|
amr_write_trailer, |
||||||
|
}; |
||||||
|
|
||||||
|
int amr_init(void) |
||||||
|
{ |
||||||
|
av_register_input_format(&amr_iformat); |
||||||
|
av_register_output_format(&amr_oformat); |
||||||
|
return 0; |
||||||
|
} |
Loading…
Reference in new issue