root/vic/branches/mpeg4/codec/encoder-h264.cpp @ 3986

Revision 3986, 5.7 KB (checked in by piers, 7 years ago)

Commented out the most prolific debug mesg

Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <math.h>
5#include <errno.h>
6#include <assert.h>
7#include <iostream>
8
9#include "inet.h"
10#include "net.h"
11#include "rtp.h"
12#include "vic_tcl.h"
13#include "transmitter.h"
14#include "pktbuf-rtp.h"
15#include "module.h"
16
17#include "databuffer.h"
18#include "x264encoder.h"
19#include "deinterlace.h"
20/*extern "C"
21{
22#include "base64.h"
23}*/
24
25static Transmitter *tx;
26static RTP_BufferPool *pool;
27static u_int32_t ts;
28static unsigned char frame_seq;
29
30class H264Encoder:public TransmitterModule
31{
32  public:
33    H264Encoder();
34    ~H264Encoder();
35
36    void setq(int q);
37    int command(int argc, const char *const *argv);
38
39    void size(int w, int h);
40    int consume(const VideoFrame *);
41
42  protected:
43    int fps, kbps, gop;
44    bool state;
45    //UCHAR* bitstream;
46
47    x264Encoder *enc;
48    DataBuffer *fOut;
49    Deinterlace deinterlacer;
50
51    FILE *fptr;
52};
53
54static class H264EncoderMatcher:public Matcher
55{
56  public:
57    H264EncoderMatcher():Matcher("module")
58    {
59    }
60    TclObject *match(const char *fmt)
61    {
62        if (strcasecmp(fmt, "h264") == 0)
63            return (new H264Encoder);
64        return (0);
65    }
66}
67
68encoder_matcher_h264;
69
70H264Encoder::H264Encoder():TransmitterModule(FT_YUV_CIF)
71{
72    enc = new x264Encoder();
73    state = false;
74    fptr = NULL;
75    frame_seq = 0;
76    fps = 20;
77    kbps = 512;
78    gop = 20;
79    fOut=NULL;
80}
81
82H264Encoder::~H264Encoder()
83{
84    delete enc;
85    if (fOut) delete fOut;
86}
87
88void H264Encoder::size(int w, int h)
89{
90    debug_msg("H264: WxH %dx%d\n", w, h);
91    Module::size(w, h);
92    fOut = new DataBuffer(w * h * 3 >> 2);
93}
94
95int H264Encoder::command(int argc, const char *const *argv)
96{
97    if (argc == 3) {
98        if (strcmp(argv[1], "q") == 0) {
99            gop = atoi(argv[2]);
100            return (TCL_OK);
101        }
102        else if (strcmp(argv[1], "fps") == 0) {
103            fps = atoi(argv[2]);
104            //std::cout << "H264: fps " << fps << "\n";
105            return (TCL_OK);
106        }
107        else if (strcmp(argv[1], "kbps") == 0) {
108            kbps = atoi(argv[2]);
109            if (kbps < 64)
110                kbps = 64;
111            //std::cout << "H264: kbps " << kbps << "\n";
112            return (TCL_OK);
113        }
114        else if (strcmp(argv[1], "hq") == 0) {
115            int enable_hq = atoi(argv[2]);
116            return (TCL_OK);
117        }
118    }
119    return (TransmitterModule::command(argc, argv));
120    return 0;
121}
122
123int H264Encoder::consume(const VideoFrame * vf)
124{
125    pktbuf *pb;
126    rtphdr *rh;
127    ts = vf->ts_;
128    tx = tx_;
129    pool = pool_;
130
131    int numNAL, i, sent_size = 0;
132    int frame_size = 0;
133    unsigned char f_seq = 0;
134    //unsigned char f_total_pkt = 0;
135    int RTP_HDR_LEN = sizeof(rtphdr);
136    int NAL_FRAG_THRESH = tx->mtu() - RTP_HDR_LEN; /* payload max in one packet */
137    //debug_msg( "MTU=%d, RTP_HDR_LEN=%d\n", NAL_FRAG_THRESH, RTP_HDR_LEN);
138
139
140    tx->flush();
141
142    if (!state) {
143            state = true;
144            size(vf->width_, vf->height_);
145            debug_msg("init x264 encoder with kbps:%d, fps:%d", kbps, fps);
146            enc->init(vf->width_, vf->height_, kbps, fps);
147            enc->setGOP(gop);
148            frame_size = vf->width_ * vf->height_;
149    }
150
151    frame_size = vf->width_ * vf->height_;
152    deinterlacer.render(vf->bp_, vf->width_, vf->height_);
153    enc->encodeFrame(vf->bp_);
154    numNAL = enc->numNAL();
155
156    //Send out numNAL packets framed according to RFC3984
157    for (i = 0; i < numNAL; i++) {
158
159        bool firstFragment = true;
160        int FU_HDR_LEN = 1;
161        int offset = 0;
162
163        enc->getNALPacket(i, fOut);
164        int nalSize1 = fOut->getDataSize();
165        int nalSize = nalSize1-5;
166        char *data1 = fOut->getData();
167        char *data = fOut->getData();
168        uint8_t NALhdr = data1[4]; //SV-XXX why does our x.264 provide 4-byte StartSync in the NALU?
169        uint8_t NALtype = NALhdr & 0x1f;
170        //debug_msg( "Got NALhdr=0x%02x, NALtype=0x%02x from encoded frame.\n", NALhdr, NALtype);
171        memcpy(data, &data1[5], nalSize);
172
173        sent_size += nalSize;
174
175
176        while (nalSize > 0) {
177            pb = pool->alloc(vf->ts_, RTP_PT_H264);
178            rh = (rtphdr *) pb->data;
179
180            if (nalSize <= NAL_FRAG_THRESH) {
181                //==============================================
182                //Single NAL or last fragment of FU-A
183                //==============================================
184
185                rh->rh_flags |= htons(RTP_M);   // set M bit
186                pb->len = nalSize + RTP_HDR_LEN + FU_HDR_LEN;
187
188                debug_msg( "NAL : ");
189
190                if (FU_HDR_LEN==2) {
191                        //==============================================
192                        //Last fragment of FU-A
193                        //==============================================
194                        pb->data[12] = 0x00 | (NALhdr & 0x60) | 28;     //FU indicator
195                        pb->data[13] = 0x40  | NALtype;                 //FU header
196                       
197                        debug_msg( "FU_Indicator=0x%02x, FU_Header=0x%02x, ", pb->data[12], pb->data[13]);
198                }
199                else {
200                        pb->data[12] = NALhdr;                          //NAL Header
201                        debug_msg( "-----------------, --------------, ");
202                }
203
204                memcpy(&pb->data[RTP_HDR_LEN + FU_HDR_LEN], data + offset, nalSize);
205
206                debug_msg( "i=%d/%d, nalSize=%4d len=%4d firstFrag=%d offset=%4d\n", i, numNAL, nalSize, pb->len, firstFragment, offset);
207
208                nalSize = 0;
209                offset = 0;
210
211            } else {
212                //==============================================
213                //FU-A (not the last fragment though)
214                //==============================================
215
216                FU_HDR_LEN = 2;
217                pb->len = (NAL_FRAG_THRESH - FU_HDR_LEN) + RTP_HDR_LEN + FU_HDR_LEN;
218
219                pb->data[12] = 0x00 | (NALhdr & 0x60) | 28;                     //FU indicator
220                pb->data[13] = ( (firstFragment) ? 0x80 : 0x00 ) | NALtype;     //FU header
221
222                memcpy(&pb->data[RTP_HDR_LEN + FU_HDR_LEN], data + offset, NAL_FRAG_THRESH - FU_HDR_LEN);
223
224                //debug_msg( "FU-A: FU_Indicator=0x%02x, FU_Header=0x%02x, i=%d/%d, nalSize=%4d len=%4d firstFrag=%d offset=%4d\n",  pb->data[12], pb->data[13], i, numNAL, nalSize, pb->len, firstFragment, offset);
225
226                nalSize -= (NAL_FRAG_THRESH-FU_HDR_LEN);
227                offset += (NAL_FRAG_THRESH-FU_HDR_LEN);
228                firstFragment = false;
229            }
230
231            tx->send(pb);
232            f_seq++;
233        }
234
235    }
236
237    frame_seq++;
238
239
240    return (kbps*1024) / (fps*8);
241}
Note: See TracBrowser for help on using the browser.