root/vic/branches/mpeg4/codec/decoder-h264.cpp @ 3942

Revision 3942, 3.5 KB (checked in by barz, 7 years ago)

* h264/mpeg4 robust decoding
* fix 16bits colorspace for win32

Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <assert.h>
5#include <iostream>
6#include "inet.h"
7#include "rtp.h"
8#include "decoder.h"
9#include "renderer.h"
10#include "packetbuffer.h"
11#include "databuffer.h"
12#include "ffmpeg_codec.h"
13
14//#define DIRECT_DISPLAY 1
15
16using namespace std;
17
18extern "C" UCHAR * video_frame;
19
20class H264Decoder:public Decoder
21{
22  public:
23    H264Decoder();
24    ~H264Decoder();
25
26    virtual void recv(pktbuf *);
27    int colorhist(u_int * hist) const;
28  protected:
29    void decode(const u_char * vh, const u_char * bp, int cc);
30    virtual void redraw();
31
32    /* packet statistics */
33    u_int16_t last_seq;         /* sequence number */
34
35    UCHAR bitstream[MAX_CODED_SIZE];    /* bitstream data */
36
37    /* collecting data for a frame */
38    int idx;
39    int last_mbit;
40    int last_iframe;
41    bool startPkt;
42
43    /* image */
44    UCHAR xxx_frame[MAX_FRAME_SIZE];
45    FFMpegCodec h264;
46    PacketBuffer *stream;
47
48
49    //For DEBUG
50    FILE *fptr;
51};
52
53static class H264DecoderMatcher:public Matcher
54{
55  public:
56    H264DecoderMatcher():Matcher("decoder")
57    {
58    }
59    TclObject *match(const char *id)
60    {
61        if (strcasecmp(id, "h264") == 0)
62            return (new H264Decoder());
63        return (0);
64    }
65}
66
67dm_h264;
68
69
70H264Decoder::H264Decoder():Decoder(2)
71{                               /* , codec_(0), */
72
73    decimation_ = 411;
74    /*
75     * Assume CIF.  Picture header will trigger a resize if
76     * we encounter QCIF instead.
77     */
78    inw_ = 0;
79    inh_ = 0;
80
81     /*XXX*/ resize(inw_, inh_);
82
83    // libavcodec
84    h264.init(false, CODEC_ID_H264, PIX_FMT_YUV420P);
85    h264.init_decoder();
86
87    idx = 0;
88    last_mbit = 0;
89    last_iframe = 0;
90    last_seq = 0;
91
92    //256 packets, each 1600 byte (default will not exceed 1600 byte)
93    //cout << "new PacketBuffer..\n";
94    stream = new PacketBuffer(1024, 1600);
95    startPkt = false;
96
97    //fptr = fopen("out.m4v", "w");
98}
99
100H264Decoder::~H264Decoder()
101{
102    delete stream;
103    //fclose(fptr);
104}
105
106int H264Decoder::colorhist(u_int * hist)  const
107{
108    return (1);
109}
110
111void H264Decoder::recv(pktbuf * pb)
112{
113    rtphdr *rh = (rtphdr *) pb->dp;
114    int hdrsize = sizeof(rtphdr) + hdrlen();
115    u_char *bp = pb->dp + hdrsize;
116    int cc = pb->len - hdrsize;
117    static int iframe_c = 0, pframe_c = 0;
118
119    int mbit = ntohs(rh->rh_flags) >> 7 & 1;
120    int seq = ntohs(rh->rh_seqno);
121    int ts = ntohl(rh->rh_ts);
122
123    if (!startPkt) {
124       stream->clear();
125       startPkt = true;
126       idx = seq;
127           last_seq = seq - 1;
128    }
129         
130    int pktIdx = seq - idx;
131    if (pktIdx < 0) {
132        pktIdx = (0xFFFF - idx) + seq;
133    }
134
135    if (abs(seq - last_seq) > 5) {
136            debug_msg("h264dec: sequece interrupt!\n");
137            idx = seq;
138            pktIdx = 0;
139            stream->clear();
140    }else if (last_seq + 1 != seq) {
141            /* oops - missing packet */
142            debug_msg("h264dec: missing packet\n");
143    }
144
145    //copy packet
146    stream->write(pktIdx, cc, (char *) bp);
147   
148    last_seq = seq;
149    int len=0;
150       
151    if (mbit) {
152            stream->setTotalPkts(pktIdx + 1);
153
154            DataBuffer *f;         
155            if (stream->isComplete()) {
156                        f = stream->getStream();
157                    len =  h264.decode((UCHAR *) f->getData(), f->getDataSize(), xxx_frame);
158            }
159           
160            if (len < 0) {
161               debug_msg("h264dec: frame error\n");
162            }
163           
164            if (inw_ != h264.width || inh_ != h264.height) {
165                        inw_ = h264.width;
166                        inh_ = h264.height;
167                        resize(inw_, inh_);
168            }
169            else {
170                        Decoder::redraw(xxx_frame);
171            }
172        stream->clear();
173            idx = seq+1;
174                     
175    }
176    pb->release();
177}
178
179void H264Decoder::redraw()
180{
181    Decoder::redraw(xxx_frame);
182}
Note: See TracBrowser for help on using the browser.