/*
 * ACT file format demuxer
 * Copyright (c) 2007-2008 Vladimir Voroshilov
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg 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.1 of the License, or (at your option) any later version.
 *
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
#include "avformat.h"
#include "riff.h"
#include "internal.h"
#include "libavcodec/get_bits.h"

#define CHUNK_SIZE 512
#define RIFF_TAG MKTAG('R','I','F','F')
#define WAVE_TAG MKTAG('W','A','V','E')

typedef struct{
    int bytes_left_in_chunk;
    uint8_t audio_buffer[22];///< temporary buffer for ACT frame
    char second_packet;      ///< 1 - if temporary buffer contains valid (second) G.729 packet
} ACTContext;

static int probe(AVProbeData *p)
{
    int i;

    if ((AV_RL32(&p->buf[0]) != RIFF_TAG) ||
        (AV_RL32(&p->buf[8]) != WAVE_TAG) ||
        (AV_RL32(&p->buf[16]) != 16))
    return 0;

    //We cant be sure that this is ACT and not regular WAV
    if (p->buf_size<512)
        return 0;

    for(i=44; i<256; i++)
        if(p->buf[i])
            return 0;

    if(p->buf[256]!=0x84)
        return 0;

    for(i=264; i<512; i++)
        if(p->buf[i])
            return 0;

    return AVPROBE_SCORE_MAX;
}

static int read_header(AVFormatContext *s)
{
    ACTContext* ctx = s->priv_data;
    AVIOContext *pb = s->pb;
    int size;
    AVStream* st;

    int min,sec,msec;

    st = avformat_new_stream(s, NULL);
    if (!st)
        return AVERROR(ENOMEM);

    avio_skip(pb, 16);
    size=avio_rl32(pb);
    ff_get_wav_header(pb, st->codec, size);

    /*
      8000Hz (Fine-rec) file format has 10 bytes long
      packets with 10ms of sound data in them
    */
    if (st->codec->sample_rate != 8000) {
        av_log(s, AV_LOG_ERROR, "Sample rate %d is not supported.\n", st->codec->sample_rate);
        return AVERROR_INVALIDDATA;
    }

    st->codec->frame_size=80;
    st->codec->channels=1;
    avpriv_set_pts_info(st, 64, 1, 100);

    st->codec->codec_id=CODEC_ID_G729;

    avio_seek(pb, 257, SEEK_SET);
    msec=avio_rl16(pb);
    sec=avio_r8(pb);
    min=avio_rl32(pb);

    st->duration = av_rescale(1000*(min*60+sec)+msec, st->codec->sample_rate, 1000 * st->codec->frame_size);

    ctx->bytes_left_in_chunk=CHUNK_SIZE;

    avio_seek(pb, 512, SEEK_SET);

    return 0;
}


static int read_packet(AVFormatContext *s,
                          AVPacket *pkt)
{
    ACTContext *ctx = s->priv_data;
    AVIOContext *pb = s->pb;
    int ret;
    int frame_size=s->streams[0]->codec->sample_rate==8000?10:22;


    if(s->streams[0]->codec->sample_rate==8000)
        ret=av_new_packet(pkt, 10);
    else
        ret=av_new_packet(pkt, 11);

    if(ret)
        return ret;

    if(s->streams[0]->codec->sample_rate==4400 && !ctx->second_packet)
    {
        ret = avio_read(pb, ctx->audio_buffer, frame_size);

        if(ret<0)
            return ret;
        if(ret!=frame_size)
            return AVERROR(EIO);

        pkt->data[0]=ctx->audio_buffer[11];
        pkt->data[1]=ctx->audio_buffer[0];
        pkt->data[2]=ctx->audio_buffer[12];
        pkt->data[3]=ctx->audio_buffer[1];
        pkt->data[4]=ctx->audio_buffer[13];
        pkt->data[5]=ctx->audio_buffer[2];
        pkt->data[6]=ctx->audio_buffer[14];
        pkt->data[7]=ctx->audio_buffer[3];
        pkt->data[8]=ctx->audio_buffer[15];
        pkt->data[9]=ctx->audio_buffer[4];
        pkt->data[10]=ctx->audio_buffer[16];

        ctx->second_packet=1;
    }
    else if(s->streams[0]->codec->sample_rate==4400 && ctx->second_packet)
    {
        pkt->data[0]=ctx->audio_buffer[5];
        pkt->data[1]=ctx->audio_buffer[17];
        pkt->data[2]=ctx->audio_buffer[6];
        pkt->data[3]=ctx->audio_buffer[18];
        pkt->data[4]=ctx->audio_buffer[7];
        pkt->data[5]=ctx->audio_buffer[19];
        pkt->data[6]=ctx->audio_buffer[8];
        pkt->data[7]=ctx->audio_buffer[20];
        pkt->data[8]=ctx->audio_buffer[9];
        pkt->data[9]=ctx->audio_buffer[21];
        pkt->data[10]=ctx->audio_buffer[10];

        ctx->second_packet=0;
    }
    else // 8000 Hz
    {
        ret = avio_read(pb, ctx->audio_buffer, frame_size);

        if(ret<0)
            return ret;
        if(ret!=frame_size)
            return AVERROR(EIO);

        pkt->data[0]=ctx->audio_buffer[5];
        pkt->data[1]=ctx->audio_buffer[0];
        pkt->data[2]=ctx->audio_buffer[6];
        pkt->data[3]=ctx->audio_buffer[1];
        pkt->data[4]=ctx->audio_buffer[7];
        pkt->data[5]=ctx->audio_buffer[2];
        pkt->data[6]=ctx->audio_buffer[8];
        pkt->data[7]=ctx->audio_buffer[3];
        pkt->data[8]=ctx->audio_buffer[9];
        pkt->data[9]=ctx->audio_buffer[4];
    }

    ctx->bytes_left_in_chunk -= frame_size;

    if(ctx->bytes_left_in_chunk < frame_size)
    {
        avio_skip(pb, ctx->bytes_left_in_chunk);
        ctx->bytes_left_in_chunk=CHUNK_SIZE;
    }

    pkt->duration=1;

    return ret;
}

AVInputFormat ff_act_demuxer = {
    .name           = "act",
    .long_name      = "ACT Voice file format",
    .priv_data_size = sizeof(ACTContext),
    .read_probe     = probe,
    .read_header    = read_header,
    .read_packet    = read_packet,
};
