[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mplayer-dev-eng
Subject:    [MPlayer-dev-eng] [RFC][PATCH] libmpcodecs/ad_spdif.c check DTS profile
From:       Naoya OYAMA <naoya.oyama () gmail ! com>
Date:       2012-02-08 14:39:23
Message-ID: CAJz3U+USUhuXvUDRgZY_z7XErDKxpoanKe1dEfT8huTiK0R16A () mail ! gmail ! com
[Download RAW message or body]

Hi,

Attached patch for ad_spdif.
Improvement enumerated below was added.

1. A suitable value is set up for bitrate and channels and dtshd_rate.
By useing DTS profile.
2. The code for creating lavc is diverted from ad_ffmpeg.c.
3. By creating lavc on ad_spdif.c, detection of bitrate and
sample_rate became highly precise.

Thanks.

["mplayer_spdif_lavc.diff" (text/x-patch)]

Index: libmpcodecs/ad_spdif.c
===================================================================
--- libmpcodecs/ad_spdif.c	(revision 34655)
+++ libmpcodecs/ad_spdif.c	(working copy)
@@ -25,6 +25,9 @@
 #include "libavformat/avformat.h"
 #include "libavcodec/avcodec.h"
 #include "libavutil/opt.h"
+#include "dec_audio.h"
+#include "help_mp.h"
+#include "libavutil/dict.h"
 
 static const ad_info_t info = {
     "libavformat/spdifenc audio pass-through decoder.",
@@ -39,11 +42,16 @@
 #define FILENAME_SPDIFENC "spdif"
 #define OUTBUF_SIZE 65536
 struct spdifContext {
+    AVCodecContext  *lavc_ctx;
     AVFormatContext *lavf_ctx;
     int              iec61937_packet_size;
+    int              init_buffer_len;
+    int              init_buffer_pos;
+    int              initialized;
     int              out_buffer_len;
     int              out_buffer_size;
     uint8_t         *out_buffer;
+    uint8_t          init_buffer[OUTBUF_SIZE];
     uint8_t          pb_buffer[OUTBUF_SIZE];
 };
 
@@ -78,24 +86,26 @@
 
 static int init(sh_audio_t *sh)
 {
-    int i, x, in_size, srate, bps, *dtshd_rate;
-    unsigned char *start;
-    double pts;
+    int i, x, srate, bps, *dtshd_rate;
+    char tmpstr[50];
     static const struct {
         const char *name; enum CodecID id;
     } fmt_id_type[] = {
-        { "aac" , CODEC_ID_AAC    },
-        { "ac3" , CODEC_ID_AC3    },
-        { "dca" , CODEC_ID_DTS    },
-        { "eac3", CODEC_ID_EAC3   },
-        { "mpa" , CODEC_ID_MP3    },
-        { "thd" , CODEC_ID_TRUEHD },
-        { NULL  , 0 }
+        { "aac"   , CODEC_ID_AAC    },
+        { "ac3"   , CODEC_ID_AC3    },
+        { "dca"   , CODEC_ID_DTS    },
+        { "eac3"  , CODEC_ID_EAC3   },
+        { "mpa"   , CODEC_ID_MP3    },
+        { "truehd", CODEC_ID_TRUEHD },
+        { NULL    , 0 }
     };
-    AVFormatContext     *lavf_ctx  = NULL;
-    AVStream            *stream    = NULL;
-    const AVOption      *opt       = NULL;
-    struct spdifContext *spdif_ctx = NULL;
+    AVFormatContext     *lavf_ctx   = NULL;
+    AVStream            *stream     = NULL;
+    AVCodecContext      *lavc_ctx   = NULL;
+    AVCodec             *lavc_codec = NULL;
+    AVDictionary        *opts       = NULL;
+    const AVOption      *opt        = NULL;
+    struct spdifContext *spdif_ctx  = NULL;
 
     spdif_ctx = av_mallocz(sizeof(*spdif_ctx));
     if (!spdif_ctx)
@@ -103,6 +113,9 @@
     spdif_ctx->lavf_ctx = avformat_alloc_context();
     if (!spdif_ctx->lavf_ctx)
         goto fail;
+    spdif_ctx->initialized     = 0;
+    spdif_ctx->init_buffer_len = 0;
+    spdif_ctx->init_buffer_pos = 0;
 
     sh->context = spdif_ctx;
     lavf_ctx    = spdif_ctx->lavf_ctx;
@@ -135,86 +148,166 @@
                "This codec is not supported by spdifenc.\n");
         goto fail;
     }
+    lavc_codec = avcodec_find_decoder_by_name(sh->codec->dll);
+    if(!lavc_codec){
+        mp_msg(MSGT_DECAUDIO,MSGL_ERR,MSGTR_MissingLAVCcodec,sh->codec->dll);
+        goto fail;
+    }
 
-    // get sample_rate & bitrate from parser
-    bps = srate = 0;
-    x = ds_get_packet_pts(sh->ds, &start, &pts);
-    in_size = x;
-    if (x <= 0) {
-        pts = MP_NOPTS_VALUE;
-        x = 0;
+    // create avcodec
+    lavc_ctx              = avcodec_alloc_context3(lavc_codec);
+    spdif_ctx->lavc_ctx   = lavc_ctx;
+    snprintf(tmpstr, sizeof(tmpstr), "%f", drc_level);
+    av_dict_set(&opts, "drc_scale", tmpstr, 0);
+    lavc_ctx->sample_rate = sh->samplerate;
+    lavc_ctx->bit_rate    = sh->i_bps * 8;
+    if(sh->wf){
+        lavc_ctx->channels              = sh->wf->nChannels;
+        lavc_ctx->sample_rate           = sh->wf->nSamplesPerSec;
+        lavc_ctx->bit_rate              = sh->wf->nAvgBytesPerSec * 8;
+        lavc_ctx->block_align           = sh->wf->nBlockAlign;
+        lavc_ctx->bits_per_coded_sample = sh->wf->wBitsPerSample;
     }
-    ds_parse(sh->ds, &start, &x, pts, 0);
-    if (x == 0) { // not enough buffer
-        srate = 48000;    //fake value
-        bps   = 768000/8; //fake value
-    } else  if (sh->avctx) {
-        if (sh->avctx->sample_rate < 44100) {
-            mp_msg(MSGT_DECAUDIO,MSGL_INFO,
-                   "This stream sample_rate[%d Hz] may be broken. "
-                   "Force reset 48000Hz.\n",
-                   sh->avctx->sample_rate);
-            srate = 48000; //fake value
-        } else
-            srate = sh->avctx->sample_rate;
-        bps = sh->avctx->bit_rate/8;
+    lavc_ctx->request_channels = audio_output_channels;
+    lavc_ctx->codec_tag        = sh->format; //FOURCC
+    lavc_ctx->codec_id         = lavc_codec->id; // not sure if required, imho not --A'rpi
+    
+    // alloc extra data
+    if (sh->wf && sh->wf->cbSize > 0) {
+        lavc_ctx->extradata = av_mallocz(sh->wf->cbSize
+                              + FF_INPUT_BUFFER_PADDING_SIZE);
+        lavc_ctx->extradata_size = sh->wf->cbSize;
+        memcpy(lavc_ctx->extradata, sh->wf + 1,
+               lavc_ctx->extradata_size);
     }
-    sh->ds->buffer_pos -= in_size;
 
+    // for QDM2
+    if (sh->codecdata_len && sh->codecdata
+        && !lavc_ctx->extradata)
+    {
+        lavc_ctx->extradata = av_malloc(sh->codecdata_len);
+        lavc_ctx->extradata_size = sh->codecdata_len;
+        memcpy(lavc_ctx->extradata, (char *)sh->codecdata,
+               lavc_ctx->extradata_size);
+    }
+
+    // open it
+    if (avcodec_open2(lavc_ctx, lavc_codec, &opts) < 0) {
+        mp_msg(MSGT_DECAUDIO,MSGL_ERR, MSGTR_CantOpenCodec);
+        return 0;
+    }
+    av_dict_free(&opts);
+    mp_msg(MSGT_DECAUDIO,MSGL_V,"INFO: libavcodec \"%s\" init OK!\n",
+           lavc_codec->name);
+
+    // Decode at least 1 byte:  (to get header filled)
+    for (x = i = 0; i < 5 && x <= 0; i++) {
+        x = decode_audio(sh, spdif_ctx->init_buffer, 1,
+                         sizeof(spdif_ctx->init_buffer));
+        spdif_ctx->init_buffer_len += x;
+    }
+#if 0
+    if (!sh->avctx) {
+        mp_msg(MSGT_DECAUDIO,MSGL_V,
+               "lavc_ctx:  bit_rate[%d] sample_rate[%d]\n",
+               lavc_ctx->bit_rate,  lavc_ctx->sample_rate);
+    } else {
+        mp_msg(MSGT_DECAUDIO,MSGL_V,
+               "lavc_ctx:  bit_rate[%d] sample_rate[%d]\n"
+               "sh->avctx: bit_rate[%d] sample_rate[%d]\n",
+               lavc_ctx->bit_rate,  lavc_ctx->sample_rate,
+               sh->avctx->bit_rate, sh->avctx->sample_rate);
+    }
+#endif
+    bps   = lavc_ctx->bit_rate;
+    if (!bps)
+        if (sh->avctx)
+            if (sh->avctx->bit_rate)
+                bps = sh->avctx->bit_rate;
+            else
+                bps = 768000;
+        else
+            bps = 768000;
+    srate = lavc_ctx->sample_rate;
+    if (!srate)
+        if (sh->avctx)
+            if(sh->avctx->sample_rate)
+                srate = sh->avctx->sample_rate;
+            else
+                srate = 48000;
+        else
+            srate = 48000;
+    sh->channels      = 2;
+    sh->i_bps         = bps/8;
+    sh->sample_format = AF_FORMAT_IEC61937_LE;
     switch (lavf_ctx->streams[0]->codec->codec_id) {
     case CODEC_ID_AAC:
         spdif_ctx->iec61937_packet_size = 16384;
-        sh->sample_format               = AF_FORMAT_IEC61937_LE;
         sh->samplerate                  = srate;
-        sh->channels                    = 2;
-        sh->i_bps                       = bps;
         break;
     case CODEC_ID_AC3:
         spdif_ctx->iec61937_packet_size = 6144;
-        sh->sample_format               = AF_FORMAT_IEC61937_LE;
         sh->samplerate                  = srate;
-        sh->channels                    = 2;
-        sh->i_bps                       = bps;
         break;
-    case CODEC_ID_DTS: // FORCE USE DTS-HD
+    case CODEC_ID_DTS:
         opt = av_opt_find(&lavf_ctx->oformat->priv_class,
                           "dtshd_rate", NULL, 0, 0);
         if (!opt)
             goto fail;
-        dtshd_rate                      = (int*)(((uint8_t*)lavf_ctx->priv_data) +
-                                          opt->offset);
-        *dtshd_rate                     = 192000*4;
-        spdif_ctx->iec61937_packet_size = 32768;
-        sh->sample_format               = AF_FORMAT_IEC61937_LE;
-        sh->samplerate                  = 192000; // DTS core require 48000
-        sh->channels                    = 2*4;
-        sh->i_bps                       = bps;
+        dtshd_rate = (int*)(((uint8_t*)lavf_ctx->priv_data) + opt->offset);
+        switch (lavc_ctx->profile) {
+        case FF_PROFILE_DTS_HD_HRA:
+            *dtshd_rate                     = 192000;
+            spdif_ctx->iec61937_packet_size = 16384;
+            sh->samplerate                  = 192000;
+            break;
+        case FF_PROFILE_DTS_HD_MA:
+            *dtshd_rate                     = 768000;
+            spdif_ctx->iec61937_packet_size = 32768;
+            sh->samplerate                  = 192000;
+            sh->channels                    = 8;
+            break;
+        case FF_PROFILE_DTS:
+        case FF_PROFILE_DTS_ES:
+        case FF_PROFILE_DTS_96_24:
+        default:
+            *dtshd_rate                     = 0;
+            spdif_ctx->iec61937_packet_size = 8192;
+            sh->samplerate                  = 48000;
+            break;
+        }
         break;
     case CODEC_ID_EAC3:
         spdif_ctx->iec61937_packet_size = 24576;
-        sh->sample_format               = AF_FORMAT_IEC61937_LE;
         sh->samplerate                  = 192000;
-        sh->channels                    = 2;
-        sh->i_bps                       = bps;
         break;
     case CODEC_ID_MP3:
         spdif_ctx->iec61937_packet_size = 4608;
         sh->sample_format               = AF_FORMAT_MPEG2;
         sh->samplerate                  = srate;
-        sh->channels                    = 2;
-        sh->i_bps                       = bps;
         break;
     case CODEC_ID_TRUEHD:
+        switch (lavc_ctx->sample_rate) {
+        case 44100:
+        case 88200:
+        case 176400:
+            sh->samplerate = 176400;
+            break;
+        case 48000:
+        case 96000:
+        case 192000:
+        default:
+            sh->samplerate = 192000;
+            break;
+        }
         spdif_ctx->iec61937_packet_size = 61440;
-        sh->sample_format               = AF_FORMAT_IEC61937_LE;
-        sh->samplerate                  = 192000;
         sh->channels                    = 8;
-        sh->i_bps                       = bps;
         break;
     default:
         break;
     }
 
+    spdif_ctx->initialized = 1;
     return 1;
 
 fail:
@@ -229,7 +322,8 @@
     AVFormatContext     *lavf_ctx  = spdif_ctx->lavf_ctx;
     AVPacket            pkt;
     double              pts;
-    int                 ret, in_size, consumed, x;
+    int                 ret, in_size, consumed, x, y;
+    int                 len = maxlen;
     unsigned char       *start = NULL;
 
     consumed = spdif_ctx->out_buffer_len  = 0;
@@ -237,6 +331,14 @@
     spdif_ctx->out_buffer      = buf;
     while (spdif_ctx->out_buffer_len + spdif_ctx->iec61937_packet_size < maxlen
            && spdif_ctx->out_buffer_len < minlen) {
+        if (spdif_ctx->init_buffer_len > 0 && spdif_ctx->initialized) {
+            x = write_packet(spdif_ctx,
+                             &spdif_ctx->init_buffer[spdif_ctx->init_buffer_pos],
+                             spdif_ctx->init_buffer_len);
+            spdif_ctx->init_buffer_pos += x;
+            spdif_ctx->init_buffer_len -= x;
+            continue;
+        }
         if (sh->ds->eof)
             break;
         x = ds_get_packet_pts(sh->ds, &start, &pts);
@@ -267,11 +369,22 @@
             sh->pts       = pts;
             sh->pts_bytes = 0;
         }
+        if (!spdif_ctx->initialized){
+	    y = avcodec_decode_audio3(spdif_ctx->lavc_ctx,
+                (int16_t*)buf, &len, &pkt);
+	    if (y == AVERROR(EAGAIN))
+	        continue;
+            if (lavf_ctx->oformat->write_packet(lavf_ctx, &pkt))
+                continue;
+            else
+                break;
+        }
         ret = lavf_ctx->oformat->write_packet(lavf_ctx, &pkt);
         if (ret < 0)
             break;
     }
-    sh->pts_bytes += spdif_ctx->out_buffer_len;
+    if (spdif_ctx->initialized)
+        sh->pts_bytes += spdif_ctx->out_buffer_len;
     return spdif_ctx->out_buffer_len;
 }
 
@@ -293,7 +406,13 @@
 {
     struct spdifContext *spdif_ctx = sh->context;
     AVFormatContext     *lavf_ctx  = spdif_ctx->lavf_ctx;
+    AVCodecContext      *lavc_ctx  = spdif_ctx->lavc_ctx;
 
+    if (lavc_ctx) {
+        avcodec_close(lavc_ctx);
+        av_freep(&lavc_ctx->extradata);
+        av_freep(&lavc_ctx);
+    }
     if (lavf_ctx) {
         if (lavf_ctx->oformat)
             lavf_ctx->oformat->write_trailer(lavf_ctx);
Index: etc/codecs.conf
===================================================================
--- etc/codecs.conf	(revision 34655)
+++ etc/codecs.conf	(working copy)
@@ -5555,7 +5555,7 @@
   fourcc ".mp1"      ; MP1 (MOV files)
   fourcc "MP3 "      ; used in .nsv files
   fourcc "LAME"      ; used in mythtv .nuv files
-  dll    mpa
+  dll    mp3
   driver spdif
 
 audiocodec spdifthd
@@ -5563,7 +5563,7 @@
   status working
   comment "needs -channels 8"
   fourcc TRHD ; internal MPlayer FourCC
-  dll    thd
+  dll    truehd
   driver spdif
 
 audiocodec ffwavesynth


_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@mplayerhq.hu
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic