[Ffmpeg-devel] [PATCH] THP PCM decoder (GSoC Qualification)

Baptiste Coudurier baptiste.coudurier
Mon Apr 2 18:25:14 CEST 2007


Hi

Marco Gerards wrote:
> Hi,
> 
> Last week I sent in a patch demuxer for THP files, which was applied
> yesterday.  Here is a patch to extend it with a PCM decoder, as
> promised.  I have tested it with the files Mike uploaded.
> 
> Mike, do you happen to have version THP version 1.1 files?  The
> current samples are all THP version 1.0.  Both should work, but you
> can't be sure until it is tested ;-).
> 
> For now I assumed it is only possible to have THP files with a single
> audio stream.  If there are THP files with more than one audio stream,
> please tell me and I will have a look :-).
> 
> --
> Marco
> 
> Index: libavcodec/allcodecs.c
> ===================================================================
> --- libavcodec/allcodecs.c	(revision 8597)
> +++ libavcodec/allcodecs.c	(working copy)
> @@ -244,6 +244,7 @@
>      REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf);
>      REGISTER_ENCDEC (ADPCM_XA, adpcm_xa);
>      REGISTER_ENCDEC (ADPCM_YAMAHA, adpcm_yamaha);
> +    REGISTER_DECODER (ADPCM_THP, adpcm_thp);

add it in alphabetical order, and with '(' aligned.

>      /* subtitles */
>      REGISTER_ENCDEC (DVBSUB, dvbsub);
> Index: libavcodec/Makefile
> ===================================================================
> --- libavcodec/Makefile	(revision 8597)
> +++ libavcodec/Makefile	(working copy)
> @@ -250,6 +250,7 @@
>  OBJS-$(CONFIG_ADPCM_XA_ENCODER)        += adpcm.o
>  OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER)    += adpcm.o
>  OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER)    += adpcm.o
> +OBJS-$(CONFIG_ADPCM_THP_DECODER)       += adpcm.o

in alphabetical order.

>  # external codec libraries
>  OBJS-$(CONFIG_LIBA52)                  += a52dec.o
> Index: libavcodec/avcodec.h
> ===================================================================
> --- libavcodec/avcodec.h	(revision 8597)
> +++ libavcodec/avcodec.h	(working copy)
> @@ -198,6 +198,7 @@
>      CODEC_ID_ADPCM_SBPRO_4,
>      CODEC_ID_ADPCM_SBPRO_3,
>      CODEC_ID_ADPCM_SBPRO_2,
> +    CODEC_ID_ADPCM_THP,
>  
>      /* AMR */
>      CODEC_ID_AMR_NB= 0x12000,
> @@ -2407,6 +2408,7 @@
>  PCM_CODEC(CODEC_ID_ADPCM_SWF,     adpcm_swf);
>  PCM_CODEC(CODEC_ID_ADPCM_XA,      adpcm_xa);
>  PCM_CODEC(CODEC_ID_ADPCM_YAMAHA,  adpcm_yamaha);
> +PCM_CODEC(CODEC_ID_ADPCM_thp,     adpcm_thp);

here too with "thp" in capital.

>  #undef PCM_CODEC
>  
> Index: libavcodec/adpcm.c
> ===================================================================
> --- libavcodec/adpcm.c	(revision 8597)
> +++ libavcodec/adpcm.c	(working copy)
> @@ -144,6 +144,7 @@
>      int coeff1;
>      int coeff2;
>      int idelta;
> +
>  } ADPCMChannelStatus;

cosmetics.

>  typedef struct ADPCMContext {
> @@ -1308,6 +1309,59 @@
>              src++;
>          }
>          break;
> +    case CODEC_ID_ADPCM_THP:
> +      {
> +        GetBitContext gb;
> +        float table[16][2];
> +        int samplecnt;
> +        int prev1[2], prev2[2];
> +        int ch;
> +
> +        init_get_bits(&gb, src, buf_size);
> +        src += buf_size;
> +
> +                    get_bits(&gb, 32); /* Channel size */
> +        samplecnt = get_bits(&gb, 32);

check for input buffer length validity.

> +        for (ch = 0; ch < 2; ch++)
> +          for (i = 0; i < 16; i++) {
> +              /* Read the fixed point entry and store as floating
> +                 point.  */
> +              int entry = get_sbits(&gb, 16);
> +              table[i][ch] = (float) entry / pow(2, 11);

1<<11

> +          }
> +
> +        /* Initialize the previous sample.  */
> +        for (ch = 0; ch < 2; ch++) {
> +            prev1[ch] = get_sbits(&gb, 16);
> +            prev2[ch] = get_sbits(&gb, 16);
> +        }
> +
> +        for (ch = 0; ch <= st; ch++) {
> +            int sample = samplecnt;
> +
> +            /* Read in every sample for this channel.  */
> +            while (sample > 0) {
> +                uint8_t index = get_bits (&gb, 4) & 7;
> +                float exp = pow(2, get_bits (&gb, 4));

1<<get_bits(&gb, 4);

> +                float factor1 = table[index * 2][ch];
> +                float factor2 = table[index * 2 + 1][ch];
> +        
> +                /* Decode 14 samples.  */
> +                for (n = 0; n < 14; n++) {
> +                    int sampledat = get_sbits (&gb, 4);
> +                    *samples = prev1[ch]*factor1 
> +                               + prev2[ch]*factor2 + sampledat * exp;
> +                    prev2[ch] = prev1[ch];
> +                    prev1[ch] = *samples++;
> +                    sample--;

check for output buffer overflow.


> +                }
> +            }
> +        }
> +
> +        break;
> +      }
> +
>      default:
>          return -1;
>      }
> @@ -1368,5 +1422,6 @@
>  ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_4, adpcm_sbpro_4);
>  ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_3, adpcm_sbpro_3);
>  ADPCM_CODEC(CODEC_ID_ADPCM_SBPRO_2, adpcm_sbpro_2);
> +ADPCM_DECODER(CODEC_ID_ADPCM_THP, adpcm_thp);

use CODEC and dummy return -1 to stay in conformance with others
(see IMA_QT)

> [...]
> +    }
> +    else {
> +       ret = av_get_packet(pb, pkt, thp->audiosize);
> +       if (ret != thp->audiosize) {
> +          av_free_packet(pkt);
> +          return AVERROR_IO;
> +       }
> +      pkt->stream_index = thp->audio_stream_index;
> +      thp->audiosize = 0;
> +      thp->frame++;

Can't seek be avoided now ? Does audio follow video in data stream ? If
so Im wondering if reading video + audio in the same time, using buffer
then output audio after, would not be cleaner and simpler.

[...]

-- 
Baptiste COUDURIER                              GnuPG Key Id: 0x5C1ABAAA
SMARTJOG S.A.                                    http://www.smartjog.com
Key fingerprint                 8D77134D20CC9220201FC5DB0AC9325C5C1ABAAA
Phone: +33 1 49966312




More information about the ffmpeg-devel mailing list