source: trunk/src/testing/app/svc/src/SVC_decode_mpeg2.cpp @ 4

Revision 4, 16.3 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1/******************************************************************************
2 * SAGE - Scalable Adaptive Graphics Environment
3 *
4 * Copyright (C) 2004 Electronic Visualization Laboratory,
5 * University of Illinois at Chicago
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above
15 *    copyright notice, this list of conditions and the following disclaimer
16 *    in the documentation and/or other materials provided with the distribution.
17 *  * Neither the name of the University of Illinois at Chicago nor
18 *    the names of its contributors may be used to endorse or promote
19 *    products derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Direct questions, comments etc about SAGE to http://www.evl.uic.edu/cavern/forum/
34 *
35 *****************************************************************************/
36
37#include "SVC_decode_mpeg2.h"
38
39#define NEEDBYTES(x)                                            \
40    do {                                                        \
41        int missing;                                            \
42                                                                \
43        missing = (x) - bytes;                                  \
44        if (missing > 0) {                                      \
45            if (header == head_buf) {                           \
46                if (missing <= end - buf) {                     \
47                    memcpy (header + bytes, buf, missing);      \
48                    buf += missing;                             \
49                    bytes = (x);                                \
50                } else {                                        \
51                    memcpy (header + bytes, buf, end - buf);    \
52                    state_bytes = bytes + end - buf;            \
53                    return 0;                                   \
54                }                                               \
55            } else {                                            \
56                memcpy (head_buf, header, bytes);               \
57                state = DEMUX_HEADER;                           \
58                state_bytes = bytes;                            \
59                return 0;                                       \
60            }                                                   \
61        }                                                       \
62    } while (0)
63
64#define DONEBYTES(x)            \
65    do {                        \
66        if (header != head_buf) \
67            buf = header + (x); \
68    } while (0)
69
70
71SVC_decode_mpeg2::SVC_decode_mpeg2()
72{
73     total_offset = 0;
74     buffer = NULL;
75     buf = NULL;
76     nextbuf = NULL;
77     data = NULL;
78     end = NULL;
79     m_output_callback = NULL;
80     m_output_obj = NULL;       //input module
81     m_output_module = NULL;    //output module
82}
83void SVC_decode_mpeg2::init(int program_id, int color_mode,int buf_size,char* output_addr, int output_port)
84{
85     m_byte_pixel = convert_format2pixelbyte(color_mode);
86     demux_pid = -1;
87     m_color_mode = color_mode;
88     m_output_addr = output_addr;
89     m_output_port = output_port;
90     buffer_size = buf_size;
91     mpeg2_initialization();
92}
93void SVC_decode_mpeg2::decode (unsigned char* input_data, int input_size)
94{
95        int pid;
96        //end = buf + fread (buf, 1, buffer + buffer_size - buf, in_file);
97        memcpy(buf,input_data,input_size);
98        //fprintf(stderr,"input_size in decode is %d\n ",input_size);
99        end = buf + input_size;
100
101        buf = buffer;
102
103        for (; (nextbuf = buf + 188) <= end; buf = nextbuf) {
104            if (*buf != 0x47) {
105                fprintf (stderr, "bad sync byte\n");
106                nextbuf = buf + 1;
107                continue;
108            }
109            pid = ((buf[1] << 8) + buf[2]) & 0x1fff;
110            if (pid != demux_pid && demux_pid != -1)
111            {
112                continue;
113            }
114            data = buf + 4;
115            if (buf[3] & 0x20) {        /* buf contains an adaptation field */
116                data = buf + 5 + buf[4];
117                if (data > nextbuf)
118                    continue;
119            }
120
121            //Begin_automatically detecting video pid
122            if((buf[1] & 0x40 && demux_pid == -1) ){            //payload unit start indicator
123                        if(((data[0] << 16) + (data[1] << 8) + data[2]) == 0x000001){   //pes start code
124                                if((data[3] >> 4) == 0xe){      //pes -> stream_id
125                                        demux_pid = pid;
126                                }
127                                else
128                                        continue;
129                        }
130                        else
131                                continue;
132            }
133            //End_automatically detecting video pid
134
135
136            if (buf[3] & 0x10)
137            {
138                demux (data, nextbuf,
139                       (buf[1] & 0x40) ? DEMUX_PAYLOAD_START : 0);
140            }
141        }
142
143        if (end != buffer + input_size)
144        {
145                fprintf(stderr,"strange size in decode()\n");
146                return;
147        }
148        memcpy (buffer, buf, end - buf);
149        buf = buffer + (end - buf);
150}
151void SVC_decode_mpeg2::mpeg2_initialization()
152{
153        mpeg2dec = mpeg2_init ();
154        if(mpeg2dec == NULL)
155        {
156                fprintf (stderr, "Can not get mpeg2dec\n");
157                exit(1);
158        }
159        mpeg2_malloc_hooks (malloc_hook, NULL);
160
161        buffer = (uint8_t *) malloc (buffer_size);
162        if (buffer == NULL || buffer_size < 188)
163                exit (1);
164        buf = buffer;
165}
166void* SVC_decode_mpeg2::malloc_hook (unsigned size, mpeg2_alloc_t reason)
167{
168        void* buf;
169        if ((int)reason < 0) {
170        return NULL;
171        }
172        buf = mpeg2_malloc (size, (mpeg2_alloc_t)-1);
173        if (buf && (reason == MPEG2_ALLOC_YUV || reason == MPEG2_ALLOC_CONVERTED))
174                memset (buf, 0, size);
175        return buf;
176}
177
178void SVC_decode_mpeg2::stop()
179{
180        mpeg2_close (mpeg2dec);
181}
182
183int SVC_decode_mpeg2::output_setup (unsigned int width,
184                         unsigned int height, unsigned int chroma_width,
185                         unsigned int chroma_height)
186{
187        m_width = width;
188        m_height = height;
189        m_chroma_width = chroma_width;
190        m_chroma_height = chroma_height;
191
192        /* setting m_convert_result according to color mode */
193        switch(m_color_mode)
194        {
195                case RGB16:
196                        m_convert_result.convert = mpeg2convert_rgb16;
197                break;
198
199                case RGB24:
200                        m_convert_result.convert = mpeg2convert_rgb24;
201                break;
202
203                case RGB32:
204                        m_convert_result.convert = mpeg2convert_rgb32;
205                break;
206
207                case YUV:
208                        m_convert_result.convert = mpeg2convert_uyvy;
209                break;
210                default:
211                        fprintf(stderr,"not supported color mode\n");
212                        return 1;
213                break;
214        }
215        return 0;
216}
217
218void SVC_decode_mpeg2::set_output_module(SVC_output_module * o_module)
219{
220        m_output_module = o_module;
221}
222void SVC_decode_mpeg2::decode_mpeg2 (uint8_t * current, uint8_t * end)
223{
224    const mpeg2_info_t * info;
225    mpeg2_state_t state;
226
227    mpeg2_buffer (mpeg2dec, current, end);
228    total_offset += end - current;
229
230    info = mpeg2_info (mpeg2dec);
231    while (1) {
232        state = mpeg2_parse (mpeg2dec);
233        switch (state) {
234        case STATE_BUFFER:
235            return;
236        case STATE_SEQUENCE:
237            /* might set nb fbuf, convert format, stride */
238            /* might set fbufs */
239            if (output_setup (info->sequence->width,
240                               info->sequence->height,
241                               info->sequence->chroma_width,
242                               info->sequence->chroma_height)) {
243                fprintf (stderr, "display setup failed\n");
244                exit (1);
245            }
246
247            if (m_convert_result.convert &&
248                mpeg2_convert (mpeg2dec, m_convert_result.convert, NULL)) {
249                fprintf (stderr, "color conversion setup failed\n");
250                exit (1);
251            }
252
253        if(m_output_module != NULL)
254            m_output_module -> init(m_width, m_height, m_color_mode,m_output_addr,m_output_port);
255
256            for (int i = 0; i < 3; i++) {
257                fbuf[i][0] = (unsigned char *) malloc (sizeof(unsigned char)*m_width*m_height*m_byte_pixel);
258                fbuf[i][1] = fbuf[i][2] = NULL;
259                if (!fbuf[i][0]) {
260                    fprintf (stderr, "Could not allocate an output buffer.\n");
261                    exit (1);
262                }
263
264                mpeg2_set_buf (mpeg2dec, fbuf[i], NULL);
265            }
266
267            mpeg2_skip (mpeg2dec, 0);   //maybe not skip
268            break;
269
270        case STATE_PICTURE:
271            /* might skip */
272            /* might set fbuf */
273            break;
274        case STATE_SLICE:
275        case STATE_END:
276        case STATE_INVALID_END:
277
278            /* draw current picture */
279            /* might free frame buffer */
280            if (info->display_fbuf) {
281                if (m_output_callback && m_output_obj)
282                    m_output_callback (m_output_obj, info->display_fbuf->buf,
283                                  info->display_fbuf->id, m_width, m_height);
284            }
285
286           /*
287                //for discard, it is not used
288            if (output->discard && info->discard_fbuf)
289                output->discard (m_output_obj, info->discard_fbuf->buf,
290                                 info->discard_fbuf->id);
291            */
292            break;
293        default:
294            break;
295        }
296    }
297
298
299}
300void SVC_decode_mpeg2::set_output_callback(void* output_obj, DECODEOUTPUT_CALLBACK callback)
301{
302        m_output_obj = output_obj;
303        m_output_callback = callback;
304}
305
306int SVC_decode_mpeg2::demux (uint8_t * buf, uint8_t * end, int flags)
307{
308        static int mpeg1_skip_table[16] = {
309            0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
310        };
311        uint8_t * header;
312        int bytes;
313        int len;
314
315        if (flags & DEMUX_PAYLOAD_START)
316                goto payload_start;
317        switch (state) {
318                case DEMUX_HEADER:
319                if (state_bytes > 0) {
320                        header = head_buf;
321                        bytes = state_bytes;
322                        goto continue_header;
323                }
324                break;
325                case DEMUX_DATA:
326                if (demux_pid || (state_bytes > end - buf)) {
327                        decode_mpeg2 (buf, end);
328                        state_bytes -= end - buf;
329                        return 0;
330                }
331                decode_mpeg2 (buf, buf + state_bytes);
332                buf += state_bytes;
333                break;
334                case DEMUX_SKIP:
335                if (demux_pid || (state_bytes > end - buf)) {
336                        state_bytes -= end - buf;
337                        return 0;
338                }
339                buf += state_bytes;
340                break;
341        }
342
343        while (1) {
344                if (demux_pid) {
345                        state = DEMUX_SKIP;
346                return 0;
347                }
348    payload_start:
349        header = buf;
350        bytes = end - buf;
351    continue_header:
352        NEEDBYTES (4);
353        if (header[0] || header[1] || (header[2] != 1)) {
354            if (demux_pid) {
355                state = DEMUX_SKIP;
356                return 0;
357            } else if (header != head_buf) {
358                buf++;
359                goto payload_start;
360            } else {
361                header[0] = header[1];
362                header[1] = header[2];
363                header[2] = header[3];
364                bytes = 3;
365                goto continue_header;
366            }
367        }
368        if (demux_pid) {
369            if ((header[3] >= 0xe0) && (header[3] <= 0xef))
370                goto pes;
371            fprintf (stderr, "bad stream id %x\n", header[3]);
372            exit (1);
373        }
374        switch (header[3]) {
375        case 0xb9:      /* program end code */
376            /* DONEBYTES (4); */
377            /* break;         */
378            return 1;
379        case 0xba:      /* pack header */
380            NEEDBYTES (5);
381            if ((header[4] & 0xc0) == 0x40) {   /* mpeg2 */
382                NEEDBYTES (14);
383                len = 14 + (header[13] & 7);
384                NEEDBYTES (len);
385                DONEBYTES (len);
386                /* header points to the mpeg2 pack header */
387            } else if ((header[4] & 0xf0) == 0x20) {    /* mpeg1 */
388                NEEDBYTES (12);
389                DONEBYTES (12);
390                /* header points to the mpeg1 pack header */
391            } else {
392                fprintf (stderr, "weird pack header\n");
393                DONEBYTES (5);
394            }
395            break;
396        default:
397            if (header[3] == demux_track) {
398            pes:
399                NEEDBYTES (7);
400                if ((header[6] & 0xc0) == 0x80) {       /* mpeg2 */
401                    NEEDBYTES (9);
402                    len = 9 + header[8];
403                    NEEDBYTES (len);
404                    /* header points to the mpeg2 pes header */
405                    if (header[7] & 0x80) {
406                        uint32_t pts, dts;
407
408                        pts = (((header[9] >> 1) << 30) |
409                               (header[10] << 22) | ((header[11] >> 1) << 15) |
410                               (header[12] << 7) | (header[13] >> 1));
411                        dts = (!(header[7] & 0x40) ? pts :
412                                (((header[14] >> 1) << 30) |
413                                (header[15] << 22) |
414                                ((header[16] >> 1) << 15) |
415                                (header[17] << 7) | (header[18] >> 1)));
416                        mpeg2_tag_picture (mpeg2dec, pts, dts);
417                    }
418                } else {        /* mpeg1 */
419                    int len_skip;
420                    uint8_t * ptsbuf;
421
422                    len = 7;
423                    while (header[len - 1] == 0xff) {
424                        len++;
425                        NEEDBYTES (len);
426                        if (len > 23) {
427                            fprintf (stderr, "too much stuffing\n");
428                            break;
429                        }
430                    }
431                    if ((header[len - 1] & 0xc0) == 0x40) {
432                        len += 2;
433                        NEEDBYTES (len);
434                    }
435                    len_skip = len;
436                    len += mpeg1_skip_table[header[len - 1] >> 4];
437                    NEEDBYTES (len);
438                    /* header points to the mpeg1 pes header */
439                    ptsbuf = header + len_skip;
440                    if ((ptsbuf[-1] & 0xe0) == 0x20) {
441                        uint32_t pts, dts;
442
443                        pts = (((ptsbuf[-1] >> 1) << 30) |
444                               (ptsbuf[0] << 22) | ((ptsbuf[1] >> 1) << 15) |
445                                (ptsbuf[2] << 7) | (ptsbuf[3] >> 1));
446                        dts = (((ptsbuf[-1] & 0xf0) != 0x30) ? pts :
447                               (((ptsbuf[4] >> 1) << 30) |
448                                (ptsbuf[5] << 22) | ((ptsbuf[6] >> 1) << 15) |
449                                (ptsbuf[7] << 7) | (ptsbuf[18] >> 1)));
450                        mpeg2_tag_picture (mpeg2dec, pts, dts);
451                    }
452                }
453                DONEBYTES (len);
454                bytes = 6 + (header[4] << 8) + header[5] - len;
455                if (demux_pid || (bytes > end - buf)) {
456                    decode_mpeg2 (buf, end);
457                    state = DEMUX_DATA;
458                    state_bytes = bytes - (end - buf);
459                    return 0;
460                } else if (bytes > 0) {
461                    decode_mpeg2 (buf, buf + bytes);
462                    buf += bytes;
463                }
464            } else if (header[3] < 0xb9) {
465                fprintf (stderr,
466                         "looks like a video stream, not system stream\n");
467                DONEBYTES (4);
468            } else {
469                NEEDBYTES (6);
470                DONEBYTES (6);
471                bytes = (header[4] << 8) + header[5];
472                if (bytes > end - buf) {
473                    state = DEMUX_SKIP;
474                    state_bytes = bytes - (end - buf);
475                    return 0;
476                }
477                buf += bytes;
478            }
479        }
480    }
481}
482
Note: See TracBrowser for help on using the repository browser.