source: svn/trunk/zas_dstar/pdrivers/mpeg2dec.c @ 2

Last change on this file since 2 was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
File size: 10.7 KB
Line 
1/*
2 * mpeg2dec.c
3 *^Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
4 *^Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
5 *
6 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
7 * See http://libmpeg2.sourceforge.net/ for updates.
8 *
9 * mpeg2dec is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * mpeg2dec is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23
24//#include "config.h"
25
26#define USE_MPEG_DISPLAY    0
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <errno.h>
32#include <signal.h>
33#include <getopt.h>
34#include "SDL.h"
35#include <inttypes.h>
36
37#include "dsthallocal.h"
38#include "dstoslayer.h"
39#include "mpeg2.h"
40#include "mpeg2priv.h"
41#include "pd_dmx_priv.h"
42
43//#include "video_out.h"
44//#include "gettimeofday.h"
45#include <sys/time.h>
46#include <time.h>
47
48#ifdef DMALLOC   
49#include <dmalloc.h>   
50#endif   
51
52static int buffer_size = 512000;
53static mpeg2dec_t * mpeg2dec;
54//static vo_open_t * output_open = NULL;
55//static vo_instance_t * output;
56static sdl_instance_t * sdl_handle;
57static int sigint = 0;
58static int total_offset = 0;
59static int verbose = 0;
60static int b_delete_fifo = 0;
61static block_fifo_t *fifo = (block_fifo_t *)NULL;
62static int b_stop_thread = 0;
63static mpeg_ud_callback_t *s_cbUserdata;
64
65void dump_state (FILE * f, mpeg2_state_t state, const mpeg2_info_t * info,
66                 int offset, int verbose);
67
68static void signal_handler (int sig)
69{
70    sigint = 1;
71    signal (sig, SIG_DFL);
72    return;
73}
74
75static void print_fps (int final, int inc)
76{
77    static uint32_t frame_counter = 0;
78    static struct timeval tv_beg, tv_start;
79    static int total_elapsed;
80    static int last_count = 0;
81    static int cnt = 0;
82    struct timeval tv_end;
83    double fps, tfps;
84    int frames, elapsed;
85
86    if (verbose)
87        return;
88
89    gettimeofday (&tv_end, NULL);
90
91    if (!frame_counter) {
92            tv_start = tv_beg = tv_end;
93            signal (SIGINT, signal_handler);
94    }
95
96    elapsed = (tv_end.tv_sec - tv_beg.tv_sec) * 100 +
97        (tv_end.tv_usec - tv_beg.tv_usec) / 10000;
98    total_elapsed = (tv_end.tv_sec - tv_start.tv_sec) * 100 +
99        (tv_end.tv_usec - tv_start.tv_usec) / 10000;
100
101    if (final) {
102        if (total_elapsed)
103            tfps = frame_counter * 100.0 / total_elapsed;
104        else
105            tfps = 0;
106
107        fprintf (stderr,"\n %s %d frames decoded in %.2f seconds (%.2f fps)\n", final ? "final" : "inprogress",
108                 frame_counter, total_elapsed / 100.0, tfps);
109
110        return;
111    }
112
113    if ( inc )
114        frame_counter++;
115    cnt++;
116    if ( cnt == 4 )
117        cnt = 0;
118       
119    if (elapsed < 50)   /* only display every 0.50 seconds */
120        return;
121
122    tv_beg = tv_end;
123    frames = frame_counter - last_count;
124
125    fps = frames * 100.0 / elapsed;
126    tfps = frame_counter * 100.0 / total_elapsed;
127
128    fprintf (stderr, "in progress %c %d frames in %.2f sec (%.2f fps), "
129             "%d last %.2f sec (%.2f fps)\033[K\r", cnt == 0 ? '-' : cnt == 1 ? '\\' : cnt == 2 ? '|' : cnt == 3 ? '/' : '.',
130             frame_counter,
131             total_elapsed / 100.0, tfps, frames, elapsed / 100.0, fps);
132
133    last_count = frame_counter;
134}
135
136static void * malloc_hook (unsigned size, mpeg2_alloc_t reason)
137{
138    void * buf;
139
140    /*
141     * Invalid streams can refer to fbufs that have not been
142     * initialized yet. For example the stream could start with a
143     * picture type onther than I. Or it could have a B picture before
144     * it gets two reference frames. Or, some slices could be missing.
145     *
146     * Consequently, the output depends on the content 2 output
147     * buffers have when the sequence begins. In release builds, this
148     * does not matter (garbage in, garbage out), but in test code, we
149     * always zero all our output buffers to:
150     * - make our test produce deterministic outputs
151     * - hint checkergcc that it is fine to read from all our output
152     *   buffers at any time
153     */
154    if ((int)reason < 0) {
155        return NULL;
156    }
157    buf = mpeg2_malloc (size, (mpeg2_alloc_t)-1);
158    if (buf && (reason == MPEG2_ALLOC_YUV || reason == MPEG2_ALLOC_CONVERTED))
159        memset (buf, 0, size);
160    return buf;
161}
162
163static void decode_mpeg2 (uint8_t * current, uint8_t * end)
164{
165    const mpeg2_info_t * info;
166    mpeg2_state_t state;
167    static int n=0;
168    //vo_setup_result_t setup_result;
169
170    mpeg2_buffer (mpeg2dec, current, end);
171    total_offset += end - current;
172
173    info = mpeg2_info (mpeg2dec);
174    while (1) {
175        state = mpeg2_parse (mpeg2dec);
176#if 0
177        if (verbose)
178            dump_state (stderr, state, info,
179                        total_offset - mpeg2_getpos (mpeg2dec), verbose);
180#endif
181
182        switch (state) {
183        case STATE_BUFFER:
184        //      sdl_discard (sdl_handle, info->discard_fbuf->buf, info->discard_fbuf->id);
185            return;
186        case STATE_SEQUENCE:
187            /* might set nb fbuf, convert format, stride */
188            /* might set fbufs */
189#if USE_MPEG_DISPLAY
190            if (sdl_setup (sdl_handle, info->sequence->width,
191                               info->sequence->height,
192                               info->sequence->chroma_width,
193                               info->sequence->chroma_height)) {
194                fprintf (stderr, "display setup failed\n");
195                exit (1);
196            }
197#if 0
198            if (setup_result.convert &&
199                mpeg2_convert (mpeg2dec, setup_result.convert, NULL)) {
200                fprintf (stderr, "color conversion setup failed\n");
201                exit (1);
202            }
203#endif
204            {
205                uint8_t * buf[3];
206                void * id;
207   
208                sdl_setup_fbuf (sdl_handle, buf, &id);
209                mpeg2_set_buf (mpeg2dec, buf, id);
210                sdl_setup_fbuf (sdl_handle, buf, &id);
211                mpeg2_set_buf (mpeg2dec, buf, id);
212                sdl_setup_fbuf (sdl_handle, buf, &id);
213                mpeg2_set_buf (mpeg2dec, buf, id);
214            }
215#endif
216            mpeg2_skip (mpeg2dec, 0/*(output->draw == NULL)*/);
217            break;
218        case STATE_PICTURE:
219            /* send userdata here. */
220            if (s_cbUserdata && info->user_data_len && info->user_data)
221            {
222                unsigned long flag;
223               
224                flag  = info->current_picture->flags & 0xFFFF;
225                if ( info->current_picture->nb_fields > 1 )
226                    flag |= (3<<16)/*FRAME*/;
227                else if ( info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST && info->current_picture->nb_fields == 1 )
228                    flag |= (1<<16)/*TOP*/;
229                else if ( info->current_picture->nb_fields == 1 )
230                    flag |= (2<<16)/*BOTTOM*/;
231                else
232                    flag |= (3<<16);
233
234                //fprintf(stderr, "|%s:%d| s_cbUserdata: 0x%08lX, s_cbUserdata: 0x%08lX\n", __func__, __LINE__, s_cbUserdata, *s_cbUserdata);
235                (*s_cbUserdata)((unsigned char *)info->user_data, info->user_data_len, (void *)flag);
236                //fprintf(stderr, "|%s:%d|\n", __func__, __LINE__);
237            }
238
239#if USE_MPEG_DISPLAY
240            /* might skip */
241            /* might set fbuf */
242                sdl_start_fbuf (sdl_handle, info->current_fbuf->buf, info->current_fbuf->id);
243#endif
244            break;
245
246        case STATE_PICTURE_2ND:
247        break;
248       
249        case STATE_SLICE:
250        case STATE_END:
251        case STATE_INVALID_END:
252            /* draw current picture */
253            /* might free frame buffer */
254#if USE_MPEG_DISPLAY
255            if (info->display_fbuf
256#if 0
257                && (n++%3) == 0
258#endif
259                ) {
260                sdl_draw_frame(sdl_handle, info->display_fbuf->buf, info->display_fbuf->id);
261                }
262
263        print_fps (0, 1);
264        sdl_discard (sdl_handle, info->discard_fbuf->buf, info->discard_fbuf->id);
265#endif
266            break;
267        default:
268            break;
269        }
270    }
271}
272
273static void es_loop (void)
274{
275    uint8_t * buffer = (uint8_t *) malloc (buffer_size);
276    uint8_t * end;
277    block_t * p_bk, *p_cur_bk;
278    int n;
279
280    if ( buffer == NULL )
281    {
282        fprintf(stderr, "!!! cannot allocate buffer (%d)\n", buffer_size);
283        return;
284    }
285   
286    do {
287        if ( b_delete_fifo == 1 || !fifo )
288        {
289            /*
290             * If user ask to delete fifo, then we will delete here.
291             */
292            if ( fifo )
293            {
294                block_FifoRelease( fifo );
295                fifo = NULL;
296
297                sdl_discard_all_buffer( sdl_handle );
298                mpeg2_reset( mpeg2dec, 1 );
299            }
300           
301            goto delay_and_continue;
302        }
303
304        print_fps(0, 0);
305       
306        p_bk = block_FifoGet( fifo );
307        if ( p_bk == (block_t *)NULL )
308            goto delay_and_continue;
309       
310        //block_ChainRelease( p_bk );
311            //continue;
312       
313        p_cur_bk = p_bk;
314       
315        if ( !p_bk->i_buffer )
316        {
317            /* no data available */
318           
319            block_ChainRelease( p_bk );
320            goto delay_and_continue;
321        }
322       
323        while ( p_cur_bk )
324        {
325            if ( !p_cur_bk->i_buffer )
326                break;
327           
328            if ( p_cur_bk->i_buffer > buffer_size )
329                fprintf(stderr, "!!! too big buffer is needed! %d\n", p_cur_bk->i_buffer);
330           
331            memcpy( buffer, p_cur_bk->p_buffer, p_cur_bk->i_buffer );
332            end = buffer + p_cur_bk->i_buffer;
333            decode_mpeg2 ( buffer, end );
334
335            p_cur_bk = p_cur_bk->p_next;
336        }
337
338        block_ChainRelease( p_bk );
339           
340            //continue;
341delay_and_continue:
342            OS_mDelay(10);
343    } while (!b_stop_thread && !sigint);
344   
345    fprintf(stderr, "\n\n\n\n\n\nmpeg decoder is ended!\n\n\n\n\n");
346    free (buffer);
347}
348
349static OS_TASK_ID s_MpegTaskId;
350void tMpegDec(DS_U32 arg)
351{
352        es_loop ();
353    print_fps (1, 1);
354}
355
356void mpeg_trigger_delete_fifo(int en)
357{
358    b_delete_fifo = en;
359}
360
361void mpeg_set_fifo(block_fifo_t *p_fifo)
362{
363    if ( fifo )
364    {
365        do {
366            OS_mDelay(1000);
367            printf("Wait for fifo to be null.\n");
368        } while (fifo);
369    }
370   
371    fifo = p_fifo;
372}
373
374int init_mpeg2dec(int width, int height)
375{
376    static int b_init = 0;
377   
378    if ( b_init == 1 )
379        return 0;
380   
381    b_init = 1;
382   
383    sdl_handle = sdl_open (width, height);
384    if (sdl_handle == NULL) {
385            fprintf (stderr, "Can not open output\n");
386            return 1;
387    }
388
389#if 1
390    mpeg2dec = mpeg2_init ();
391    if (mpeg2dec == NULL)
392    {
393        fprintf(stderr, "!!! cannot initialize mpeg2dec\n");
394            return 1;
395        }
396#endif
397
398        s_MpegTaskId = OS_SpawnTask( tMpegDec, "tMpegDec", 0, 0, (DS_U32)0);
399        if (s_MpegTaskId == (OS_TASK_ID)NULL)
400        {
401            printf("Cannot create tMpegDec task\n");
402            return 1;
403        }
404
405    mpeg2_malloc_hooks (malloc_hook, NULL);
406
407    return 0;
408}
409
410int close_mpeg2dec()
411{
412    b_stop_thread = 1;
413    mpeg2_close (mpeg2dec);
414   
415    return 0;
416}
417
418void mpeg_set_userdata_callback(void *cbUserdata)
419{
420//    printf("s_cbUserdata <- 0x%08lX\n", cbUserdata);
421    s_cbUserdata = cbUserdata;
422}
Note: See TracBrowser for help on using the repository browser.