On 31 March 2010 05:25, Stefano Sabatini <[email protected]>wrote:

[...]

Fixed the specified issues. Added an rtp depacketizer.

Regards,
Naufal
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 4667be2..860c4bd 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -129,6 +129,7 @@ OBJS-$(CONFIG_FLIC_DECODER)            += flicvideo.o
 OBJS-$(CONFIG_FOURXM_DECODER)          += 4xm.o
 OBJS-$(CONFIG_FRAPS_DECODER)           += fraps.o huffman.o
 OBJS-$(CONFIG_FRWU_DECODER)            += frwu.o
+OBJS-$(CONFIG_G723_1_DECODER)          += g723_1parser.o
 OBJS-$(CONFIG_GIF_DECODER)             += gifdec.o lzw.o
 OBJS-$(CONFIG_GIF_ENCODER)             += gif.o lzwenc.o
 OBJS-$(CONFIG_H261_DECODER)            += h261dec.o h261.o \
diff --git a/libavcodec/g723_1parser.c b/libavcodec/g723_1parser.c
new file mode 100644
index 0000000..b968c0e
--- /dev/null
+++ b/libavcodec/g723_1parser.c
@@ -0,0 +1,176 @@
+#include "libavutil/intreadwrite.h"
+
+#include "avcodec.h"
+#include "get_bits.h"
+
+#define PITCH_MIN 18
+
+/*
+ *  G723.1 frame types
+ */
+typedef enum {
+    Frame6k3,           ///< 6.3 kbps frame rate
+    Frame5k3,           ///< 5.3 kbps frame rate
+    FrameSID,           ///< silence insertion descriptor frame
+    FrameUntransmitted
+} FrameType;
+
+typedef enum {
+    Rate6k3,
+    Rate5k3
+} Rate;
+
+/*
+ *  G723.1 unpacked data subframe
+ */
+typedef struct {
+    uint16_t ad_cb_lag;     ///< adaptive codebook lag
+    uint16_t pitch_lag;
+    uint16_t combined_gain;
+    uint16_t pulse_pos;
+    uint16_t pulse_sign;
+    uint16_t grid_index;
+    uint16_t amp_index;     ///< for SID frames
+} G723_1_Subframe;
+
+/*
+ *  G723.1 unpacked data frame 
+ */
+typedef struct {
+    uint32_t lsp_index;
+    G723_1_Subframe subframe[4];
+} G723_1_Frame;
+
+typedef struct g723_1_context {
+    G723_1_Frame frame;
+    FrameType cur_frame_type;
+    Rate cur_rate;
+    int is_bad_frame;
+} G723_1_Context;
+
+/*
+ * Unpack the frame into parameters.
+ *
+ * @param p           the context
+ * @param buf         pointer to the input buffer 
+ * @param buf_size    size of the input buffer
+ */
+static void unpack_bitstream(G723_1_Context *p, const uint8_t *buf,
+                                       int buf_size)
+{
+    GetBitContext gb;
+    G723_1_Frame *frame = &p->frame;
+    uint32_t temp;
+
+    init_get_bits(&gb, buf, buf_size * 8);
+
+    // Extract frame type and rate info
+    p->cur_frame_type = get_bits(&gb, 2);
+
+    if (p->cur_frame_type == FrameUntransmitted)
+        return;
+
+    frame->lsp_index = get_bits(&gb, 24);
+
+    if (p->cur_frame_type == FrameSID) {
+        frame->subframe[0].amp_index = get_bits(&gb, 6);
+        return;
+    }
+
+    // Extract the info common to both rates
+    p->cur_rate = (p->cur_frame_type == 0) ? Rate6k3 : Rate5k3;
+
+    temp = get_bits(&gb, 7);
+    if (temp <= 123) {       // test if forbidden code
+        frame->subframe[0].pitch_lag = temp + PITCH_MIN;
+    } else {
+        p->is_bad_frame  = 1; // transmission error
+        return;
+    }
+
+    frame->subframe[1].ad_cb_lag  = get_bits(&gb, 2);
+
+    temp = get_bits(&gb, 7);
+    if (temp <= 123) {
+        frame->subframe[1].pitch_lag = temp + PITCH_MIN;
+    } else {
+        p->is_bad_frame = 1;
+        return;
+    }
+
+    frame->subframe[3].ad_cb_lag  = get_bits(&gb, 2);
+
+    frame->subframe[0].ad_cb_lag  = 1;
+    frame->subframe[2].ad_cb_lag  = 1;
+
+    frame->subframe[0].combined_gain = get_bits(&gb, 12);
+    frame->subframe[1].combined_gain = get_bits(&gb, 12);
+    frame->subframe[2].combined_gain = get_bits(&gb, 12);
+    frame->subframe[3].combined_gain = get_bits(&gb, 12);
+
+    frame->subframe[0].grid_index = get_bits(&gb, 1);
+    frame->subframe[1].grid_index = get_bits(&gb, 1);
+    frame->subframe[2].grid_index = get_bits(&gb, 1);
+    frame->subframe[3].grid_index = get_bits(&gb, 1);
+
+    if (p->cur_frame_type == Frame6k3) {
+        skip_bits(&gb, 1);  // skip reserved bit
+
+        // Compute pulse_pos index using the 13bit combined position index
+        temp = get_bits(&gb, 13);
+        frame->subframe[0].pulse_pos = (temp / 90) / 9;
+        frame->subframe[1].pulse_pos = (temp / 90) % 9;
+        frame->subframe[2].pulse_pos = (temp % 90) / 9;
+        frame->subframe[3].pulse_pos = (temp % 90) % 9;
+
+        frame->subframe[0].pulse_pos = (frame->subframe[0].pulse_pos << 16) +
+                                       get_bits(&gb, 16);
+        frame->subframe[1].pulse_pos = (frame->subframe[1].pulse_pos << 14) +
+                                       get_bits(&gb, 14);
+        frame->subframe[2].pulse_pos = (frame->subframe[2].pulse_pos << 16) +
+                                       get_bits(&gb, 16);
+        frame->subframe[3].pulse_pos = (frame->subframe[3].pulse_pos << 14) +
+                                       get_bits(&gb, 14);
+
+        frame->subframe[0].pulse_sign = get_bits(&gb, 6);
+        frame->subframe[1].pulse_sign = get_bits(&gb, 5);
+        frame->subframe[2].pulse_sign = get_bits(&gb, 6);
+        frame->subframe[3].pulse_sign = get_bits(&gb, 5);
+    } else { // Frame5k3
+        frame->subframe[0].pulse_pos  = get_bits(&gb, 12);
+        frame->subframe[1].pulse_pos  = get_bits(&gb, 12);
+        frame->subframe[2].pulse_pos  = get_bits(&gb, 12);
+        frame->subframe[3].pulse_pos  = get_bits(&gb, 12);
+
+        frame->subframe[0].pulse_sign = get_bits(&gb, 4);
+        frame->subframe[1].pulse_sign = get_bits(&gb, 4);
+        frame->subframe[2].pulse_sign = get_bits(&gb, 4);
+        frame->subframe[3].pulse_sign = get_bits(&gb, 4);
+    }
+}
+
+static int g723_1_parse_frame(AVCodecContext *avctx, void *data,
+                               int *data_size, AVPacket *avpkt)
+{
+    G723_1_Context *p  = avctx->priv_data;
+    const uint8_t *buf = avpkt->data;
+    int buf_size       = avpkt->size;
+
+    unpack_bitstream(p, buf, buf_size);
+
+    if (p->is_bad_frame) {
+        av_log(avctx, AV_LOG_ERROR, "Bad frame\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    return 0;
+}
+
+AVCodec g723_1_decoder = {
+    .name           = "g723_1",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = CODEC_ID_G723_1,
+    .priv_data_size = sizeof(G723_1_Context),
+    .decode         = g723_1_parse_frame,
+    .long_name      = NULL_IF_CONFIG_SMALL("G.723.1"),
+};
diff --git a/libavformat/Makefile b/libavformat/Makefile
index bcdf3f5..cb1f4a6 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -217,14 +217,15 @@ OBJS-$(CONFIG_RTP_MUXER)                 += rtp.o         \
                                             avc.o
 OBJS-$(CONFIG_RTSP_DEMUXER)              += rtsp.o httpauth.o
 OBJS-$(CONFIG_RTSP_MUXER)                += rtsp.o rtspenc.o httpauth.o
-OBJS-$(CONFIG_SDP_DEMUXER)               += rtsp.o        \
-                                            rdt.o         \
-                                            rtp.o         \
-                                            rtpdec.o      \
-                                            rtpdec_amr.o  \
-                                            rtpdec_asf.o  \
-                                            rtpdec_h263.o \
-                                            rtpdec_h264.o \
+OBJS-$(CONFIG_SDP_DEMUXER)               += rtsp.o          \
+                                            rdt.o           \
+                                            rtp.o           \
+                                            rtpdec.o        \
+                                            rtpdec_amr.o    \
+                                            rtpdec_asf.o    \
+                                            rtpdec_g723_1.o \
+                                            rtpdec_h263.o   \
+                                            rtpdec_h264.o   \
                                             rtpdec_theora.o \
                                             rtpdec_vorbis.o
 OBJS-$(CONFIG_SEGAFILM_DEMUXER)          += segafilm.o
diff --git a/libavformat/rtp.c b/libavformat/rtp.c
index a8dcfd7..b7ab999 100644
--- a/libavformat/rtp.c
+++ b/libavformat/rtp.c
@@ -43,7 +43,7 @@ static const struct
 {
   {0, "PCMU",        AVMEDIA_TYPE_AUDIO,   CODEC_ID_PCM_MULAW, 8000, 1},
   {3, "GSM",         AVMEDIA_TYPE_AUDIO,   CODEC_ID_NONE, 8000, 1},
-  {4, "G723",        AVMEDIA_TYPE_AUDIO,   CODEC_ID_NONE, 8000, 1},
+  {4, "G723",        AVMEDIA_TYPE_AUDIO,   CODEC_ID_G723_1, 8000, 1},
   {5, "DVI4",        AVMEDIA_TYPE_AUDIO,   CODEC_ID_NONE, 8000, 1},
   {6, "DVI4",        AVMEDIA_TYPE_AUDIO,   CODEC_ID_NONE, 16000, 1},
   {7, "LPC",         AVMEDIA_TYPE_AUDIO,   CODEC_ID_NONE, 8000, 1},
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index e329ad2..66a0f9f 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -32,6 +32,7 @@
 #include "rtpdec.h"
 #include "rtpdec_amr.h"
 #include "rtpdec_asf.h"
+#include "rtpdec_g723_1.c"
 #include "rtpdec_h263.h"
 #include "rtpdec_h264.h"
 #include "rtpdec_vorbis.h"
@@ -66,6 +67,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
     ff_register_dynamic_payload_handler(&mpeg4_generic_handler);
     ff_register_dynamic_payload_handler(&ff_amr_nb_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_amr_wb_dynamic_handler);
+    ff_register_dynamic_payload_handler(&ff_g723_1_handler);
     ff_register_dynamic_payload_handler(&ff_h263_1998_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_h263_2000_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);
diff --git a/libavformat/rtpdec_g723_1.c b/libavformat/rtpdec_g723_1.c
new file mode 100644
index 0000000..0b5f24b
--- /dev/null
+++ b/libavformat/rtpdec_g723_1.c
@@ -0,0 +1,63 @@
+/*
+ * RTP G.723.1 Depacketizer, RFC 3551, 3555
+ */
+#include "avformat.h"
+#include "rtpdec_g723_1.h"
+#include "libavutil/avstring.h"
+
+static const uint8_t frame_sizes[4] = {24, 20, 4, 1};
+
+static int g723_1_handle_packet(AVFormatContext *ctx,
+                                PayloadContext *data,
+                                AVStream *st,
+                                AVPacket *pkt,
+                                uint32_t *timestamp,
+                                const uint8_t *buf,
+                                int len, int flags)
+{
+    int frame_len;
+    uint8_t *ptr;
+
+    if (st->codec->codec_id != CODEC_ID_G723_1) {
+        av_log(ctx, AV_LOG_ERROR, "Bad codec ID\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (st->codec->channels != 1) {
+        av_log(ctx, AV_LOG_ERROR, "G.723.1 supports mono only");
+        return AVERROR_INVALIDDATA;
+    }
+
+    // The frame size and codec type is determined from
+    // the least 2 bits of the first byte.
+    frame_len         = frame_sizes[buf[0] & 3];
+    pkt->stream_index = st->index;
+    ptr               = pkt->data;
+
+    if (av_new_packet(pkt, len) < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
+        return AVERROR_NOMEM;
+    }
+
+    if (frame_len > len)
+        av_log(ctx, AV_LOG_WARNING, "Too little data in the RTP packet\n");
+
+    memcpy(ptr, buf, len);
+    pkt->size = len;
+
+    if (frame_len < len) {
+        av_log(ctx, AV_LOG_WARNING, "Too much data in the RTP packet\n");
+        ptr += frame_len;
+        memset(ptr, 0, len - frame_len);
+        pkt->size = frame_len;
+    }
+
+    return 0;
+}
+
+RTPDynamicProtocolHandler ff_g723_1_handler = {
+    .enc_name         = "G723",
+    .codec_type       = AVMEDIA_TYPE_AUDIO,
+    .codec_id         = CODEC_ID_G723_1,
+    .parse_packet     = g723_1_handle_packet,
+};
diff --git a/libavformat/rtpdec_g723_1.h b/libavformat/rtpdec_g723_1.h
new file mode 100644
index 0000000..76da2f1
--- /dev/null
+++ b/libavformat/rtpdec_g723_1.h
@@ -0,0 +1,8 @@
+#ifndef AVFORMAT_RTPDEC_G723_1_H
+#define AVFORMAT_RTPDEC_G723_1_H
+
+#include "rtpdec.h"
+
+extern RTPDynamicProtocolHandler ff_g723_1_handler;
+
+#endif /* AVFORMAT_RTPDEC_AMR_H */
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc

Reply via email to