diff options
author | Vladimir Voroshilov <voroshil@gmail.com> | 2011-09-24 22:08:16 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-09-24 22:10:46 +0200 |
commit | 0f2297a9b958b8598b17f139e7ec2d7e593a0a7c (patch) | |
tree | 9d7684260ece037038d87b793e28856c2d342ddd | |
parent | 780d45473c32fa356c8ce385c3ea4692567c3228 (diff) | |
download | ffmpeg-streaming-0f2297a9b958b8598b17f139e7ec2d7e593a0a7c.zip ffmpeg-streaming-0f2297a9b958b8598b17f139e7ec2d7e593a0a7c.tar.gz |
Add .bit (de)muxer
-rw-r--r-- | libavformat/bit.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/libavformat/bit.c b/libavformat/bit.c new file mode 100644 index 0000000..ad55a55 --- /dev/null +++ b/libavformat/bit.c @@ -0,0 +1,150 @@ +#include "avformat.h" +#include "libavcodec/get_bits.h" +#include "libavcodec/put_bits.h" + +#define MAX_FRAME_SIZE 10 + +#define SYNC_WORD 0x6b21 +#define BIT_0 0x7f +#define BIT_1 0x81 + +static int probe(AVProbeData *p) +{ + int i; + i=AV_RL16(&p->buf[0]); +av_log(NULL, AV_LOG_ERROR, "bit probe: %x\n", i); + if(i != SYNC_WORD) + return 0; + + switch(AV_RL16(&p->buf[2])) + { + case 0x40: + case 0x50: + return AVPROBE_SCORE_MAX/2; + default: + return 0; + } +} + +static int read_header(AVFormatContext *s, AVFormatParameters *ap) +{ + AVStream* st; + ByteIOContext *pb = s->pb; + + st=av_new_stream(s, 0); + if (!st) + return AVERROR(ENOMEM); + + url_fskip(pb, 2); + switch(get_le16(pb)) + { + case 0x40: + st->codec->bit_rate = 6400; + break; + case 0x50: + st->codec->bit_rate = 8000; + break; + } + + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id=CODEC_ID_G729; + st->codec->sample_rate=8000; + st->codec->block_align = 16; + st->codec->channels=1; + + av_set_pts_info(st, 64, 1, 100); + url_fseek(pb, 0, SEEK_SET); + return 0; +} + +static int read_packet(AVFormatContext *s, + AVPacket *pkt) +{ + ByteIOContext *pb = s->pb; + PutBitContext pbo; + uint16_t buf[8 * MAX_FRAME_SIZE + 2]; + int packet_size; + int sync; + uint16_t* src=buf; + int i, j, ret; + + if(url_feof(pb)) + return AVERROR(EIO); + + sync = get_le16(pb); // sync word + packet_size = get_le16(pb) / 8; + assert(packet_size < 8 * MAX_FRAME_SIZE); + + ret = get_buffer(pb, (uint8_t*)buf, (8 * packet_size) * sizeof(uint16_t)); + if(ret<0) + return ret; + if(ret != 8 * packet_size * sizeof(uint16_t)) + return AVERROR(EIO); + + av_new_packet(pkt, packet_size); + + init_put_bits(&pbo, pkt->data, packet_size); + for(j=0; j < packet_size; j++) + for(i=0; i<8;i++) + put_bits(&pbo,1, AV_RL16(src++) == BIT_1 ? 1 : 0); + + flush_put_bits(&pbo); + + pkt->duration=1; + return 0; +} + +AVInputFormat ff_bit_demuxer = { + "bit", + "G.729 BIT file format", + 0, + probe, + read_header, + read_packet, + .extensions = "bit" +}; + +#ifdef CONFIG_MUXERS +static int write_header(AVFormatContext *s) +{ + AVCodecContext *enc = s->streams[0]->codec; + + enc->codec_id = CODEC_ID_G729; + enc->channels = 1; + enc->bits_per_coded_sample = 16; + enc->block_align = (enc->bits_per_coded_sample * enc->channels) >> 3; + + return 0; +} + +static int write_packet(AVFormatContext *s, AVPacket *pkt) +{ + ByteIOContext *pb = s->pb; + GetBitContext gb; + int i; + uint16_t b; + + put_le16(pb, SYNC_WORD); + put_le16(pb, 8 * 10); + + init_get_bits(&gb, pkt->data, 8*10); + for(i=0; i< 8 * 10; i++) + put_le16(pb, get_bits1(&gb) ? BIT_1 : BIT_0); + put_flush_packet(pb); + + return 0; +} + +AVOutputFormat ff_bit_muxer = { + "bit", + "G.729 BIT file format", + "audio/bit", + "bit", + 0, + CODEC_ID_G729, + CODEC_ID_NONE, + write_header, + write_packet, + .extensions = "bit" +}; +#endif |