On 1 April 2010 02:14, Ronald S. Bultje <[email protected]> wrote:
> Hi,
>
> On Wed, Mar 31, 2010 at 10:52 AM, Mohamed Naufal <[email protected]>
> wrote:
> > Fixed the specified issues. Added an rtp depacketizer.
>
> > + 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;
> > + }
>
> return -1, and then handle the return value. That way you don't need
> the (usually unused) bad_frame member in the context.
>
Fixed.
>
> > + 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);
>
> for (i = 0; i < 4; i++) ..
>
> Saves 3 lines of code, and the compiler will unroll it anyway.
>
Fixed.
>
> > + 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;
>
> Try using FASTDIV() here, and cache the result so you don't need the
> %, but you can use temp - result * 90 (faster).
>
Done.
>
> > + 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);
> > + }
>
> More loopable stuff.
>
> > +++ b/libavformat/rtpdec_g723_1.c
> [..]
> > + 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;
> > + }
>
> Both can be removed, decoder should check that, not RTP depacketizer.
>
Removed.
>
> > + // 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;
> > + }
>
> That looks messy, are you sure that's correct? I figure frames are
> generally small and RTP packets would be bigger, so this would trigger
> all the time. Shouldn't this split the packets? Or simply copy them
> all (as the AMR depacketizer does)?
>
You're right. Sorry. Corrected now. I suppose I'll need a parser too. I
believe the (yet to be committed) amr parser can be modified for this too.
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..96a52cc
--- /dev/null
+++ b/libavcodec/g723_1parser.c
@@ -0,0 +1,167 @@
+#include "avcodec.h"
+#define ALT_BITSTREAM_READER_LE
+#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;
+} 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 int unpack_bitstream(G723_1_Context *p, const uint8_t *buf,
+ int buf_size)
+{
+ GetBitContext gb;
+ G723_1_Frame *frame = &p->frame;
+ uint32_t temp;
+ int i;
+
+ 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 0;
+
+ frame->lsp_index = get_bits(&gb, 24);
+
+ if (p->cur_frame_type == FrameSID) {
+ frame->subframe[0].amp_index = get_bits(&gb, 6);
+ return 0;
+ }
+
+ // Extract the info common to both rates
+ p->cur_rate = (!p->cur_frame_type) ? Rate6k3 : Rate5k3;
+
+ temp = get_bits(&gb, 7);
+ if (temp <= 123) // test if forbidden code
+ frame->subframe[0].pitch_lag = temp + PITCH_MIN;
+ else
+ return -1; // transmission error
+
+ 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
+ return -1;
+
+ frame->subframe[3].ad_cb_lag = get_bits(&gb, 2);
+
+ frame->subframe[0].ad_cb_lag = 1;
+ frame->subframe[2].ad_cb_lag = 1;
+
+ for (i = 0; i < 4; i++)
+ frame->subframe[i].combined_gain = get_bits(&gb, 12);
+
+ for (i = 0; i < 4; i++)
+ frame->subframe[i].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 / 810;
+
+ temp -= frame->subframe[0].pulse_pos * 810;
+ frame->subframe[1].pulse_pos = FASTDIV(temp, 90);
+
+ temp -= frame->subframe[1].pulse_pos * 90;
+ frame->subframe[2].pulse_pos = FASTDIV(temp, 9);
+ frame->subframe[3].pulse_pos = temp - frame->subframe[2].pulse_pos * 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
+ for (i = 0; i < 4; i++)
+ frame->subframe[i].pulse_pos = get_bits(&gb, 12);
+
+ for (i = 0; i < 4; i++)
+ frame->subframe[i].pulse_sign = get_bits(&gb, 4);
+ }
+
+ return 0;
+}
+
+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;
+
+ if (unpack_bitstream(p, buf, buf_size) < 0) {
+ 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..58a3965
--- /dev/null
+++ b/libavformat/rtpdec_g723_1.c
@@ -0,0 +1,52 @@
+/*
+ * 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[3] = {24, 20, 4};
+
+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 frames;
+ int pkt_size = len;
+
+ /* The frame size and codec type is determined from the HDR bits
+ * (buf[frames] & 3) in the first octet of a frame.
+ */
+ for (frames = 0; frames < len && (buf[frames] & 3) != 3;
+ frames += frame_sizes[buf[frames] & 3]);
+
+ if (frames > len) {
+ av_log(ctx, AV_LOG_WARNING, "Too little data in the RTP packet\n");
+ } else if (frames < len) {
+ /* This block is executed when the HDR bits are 0b11.
+ * But this is reserved for future use.
+ */
+ av_log(ctx, AV_LOG_WARNING, "Found an invalid frame!\n");
+ pkt_size = frames;
+ }
+
+ if (av_new_packet(pkt, pkt_size) < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
+ return AVERROR_NOMEM;
+ }
+
+ pkt->stream_index = st->index;
+ memcpy(pkt->data, buf, pkt_size);
+ 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..10b69c8
--- /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_G723_1_H */
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc