qtffutil.h

00001 #ifndef QTFFUTIL_H_
00002 #define QTFFUTIL_H_
00003 
00004 // Note: this header is derived from ffplay - hence the almost complete lack of 
00005 // documentation.
00006 
00007 #ifdef CONFIG_OS2
00008       MorphToPM(); // Morph the VIO application to a PM one to be able to use Win* functions
00009       // Make stdout and stderr unbuffered
00010       setbuf( stdout, NULL );
00011       setbuf( stderr, NULL );
00012 #endif
00013 
00014 // Definitions
00015 AVPicture grabPict;
00016 extern Uint8 *dataR, *dataG, *dataB, *dataA;
00017 
00018 extern int globWidth, globHeight;
00019 extern int globLine0, globLine1, globLine2;
00020 
00021 void packet_queue_init(PacketQueue *q);
00022 void packet_queue_flush(PacketQueue *q);
00023 void packet_queue_end(PacketQueue *q);
00024 int packet_queue_put(PacketQueue *q, AVPacket *pkt);
00025 void packet_queue_abort(PacketQueue *q);
00026 int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block);
00027 Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque);
00028 double get_audio_clock(VideoState *is);
00029 double get_video_clock(VideoState *is);
00030 double get_external_clock(VideoState *is);
00031 void stream_pause(VideoState *is);
00032 int queue_picture(VideoState *is, AVFrame *src_frame, double pts);
00033 int output_picture2(VideoState *is, AVFrame *src_frame, double pts1);
00034 int video_thread(void *arg);
00035 int subtitle_thread(void *arg);
00036 void update_sample_display(VideoState *is, short *samples, int samples_size);
00037 int synchronize_audio(VideoState *is, short *samples,int samples_size1, double pts);
00038 int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr);
00039 int audio_write_get_buf_size(VideoState *is);
00040 void sdl_audio_callback(void *opaque, Uint8 *stream, int len);
00041 int stream_component_open(VideoState *is, int stream_index);
00042 void stream_component_close(VideoState *is, int stream_index);
00043 void dump_stream_info(AVFormatContext *s);
00044 int decode_interrupt_cb(void);
00045 int decode_thread(void *arg);
00046         
00047 
00048 /* packet queue handling */
00049 void packet_queue_init(PacketQueue *q)
00050 {
00051     memset(q, 0, sizeof(PacketQueue));
00052     q->mutex = SDL_CreateMutex();
00053     q->cond = SDL_CreateCond();
00054 }
00055 
00056 void packet_queue_flush(PacketQueue *q)
00057 {
00058     AVPacketList *pkt, *pkt1;
00059 
00060     SDL_LockMutex(q->mutex);
00061     for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
00062         pkt1 = pkt->next;
00063         av_free_packet(&pkt->pkt);
00064         av_freep(&pkt);
00065     }
00066     q->last_pkt = NULL;
00067     q->first_pkt = NULL;
00068     q->nb_packets = 0;
00069     q->size = 0;
00070     SDL_UnlockMutex(q->mutex);
00071 }
00072 
00073 void packet_queue_end(PacketQueue *q)
00074 {
00075     packet_queue_flush(q);
00076     SDL_DestroyMutex(q->mutex);
00077     SDL_DestroyCond(q->cond);
00078 }
00079 
00080 int packet_queue_put(PacketQueue *q, AVPacket *pkt)
00081 {
00082     AVPacketList *pkt1;
00083 
00084     /* duplicate the packet */
00085     if (av_dup_packet(pkt) < 0)
00086         return -1;
00087 
00088     pkt1 = (AVPacketList*) av_malloc(sizeof(AVPacketList));
00089     if (!pkt1)
00090         return -1;
00091     pkt1->pkt = *pkt;
00092     pkt1->next = NULL;
00093 
00094 
00095     SDL_LockMutex(q->mutex);
00096 
00097     if (!q->last_pkt)
00098 
00099         q->first_pkt = pkt1;
00100     else
00101         q->last_pkt->next = pkt1;
00102     q->last_pkt = pkt1;
00103     q->nb_packets++;
00104     q->size += pkt1->pkt.size;
00105     /* XXX: should duplicate packet data in DV case */
00106     SDL_CondSignal(q->cond);
00107 
00108     SDL_UnlockMutex(q->mutex);
00109     return 0;
00110 }
00111 
00112 void packet_queue_abort(PacketQueue *q)
00113 {
00114     SDL_LockMutex(q->mutex);
00115 
00116     q->abort_request = 1;
00117 
00118     SDL_CondSignal(q->cond);
00119 
00120     SDL_UnlockMutex(q->mutex);
00121 }
00122 
00123 /* return < 0 if aborted, 0 if no packet and > 0 if packet.  */
00124 int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
00125 {
00126     AVPacketList *pkt1;
00127     int ret;
00128 
00129     SDL_LockMutex(q->mutex);
00130 
00131     for(;;) {
00132         if (q->abort_request) {
00133             ret = -1;
00134             break;
00135         }
00136 
00137         pkt1 = q->first_pkt;
00138         if (pkt1) {
00139             q->first_pkt = pkt1->next;
00140             if (!q->first_pkt)
00141                 q->last_pkt = NULL;
00142             q->nb_packets--;
00143             q->size -= pkt1->pkt.size;
00144             *pkt = pkt1->pkt;
00145             av_free(pkt1);
00146             ret = 1;
00147             break;
00148         } else if (!block) {
00149             ret = 0;
00150             break;
00151         } else {
00152             SDL_CondWait(q->cond, q->mutex);
00153         }
00154     }
00155     SDL_UnlockMutex(q->mutex);
00156     return ret;
00157 }
00158 
00159 Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
00160 {
00161     SDL_Event event;
00162     event.type = FF_REFRESH_EVENT;
00163     event.user.data1 = opaque;
00164     SDL_PushEvent(&event);
00165     return 0; /* 0 means stop timer */
00166 }
00167 
00168 /* get the current audio clock value */
00169 double get_audio_clock(VideoState *is)
00170 {
00171     double pts;
00172     int hw_buf_size, bytes_per_sec;
00173     pts = is->audio_clock;
00174     hw_buf_size = audio_write_get_buf_size(is);
00175     bytes_per_sec = 0;
00176     if (is->audio_st) {
00177         bytes_per_sec = is->audio_st->codec->sample_rate *
00178                 2 * is->audio_st->codec->channels;
00179     }
00180     if (bytes_per_sec)
00181         pts -= (double)hw_buf_size / bytes_per_sec;
00182     return pts;
00183 }
00184 
00185 /* get the current video clock value */
00186 double get_video_clock(VideoState *is)
00187 {
00188     double delta;
00189     if (is->paused) {
00190         delta = 0;
00191     } else {
00192         delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;
00193     }
00194     return is->video_current_pts + delta;
00195 }
00196 
00197 /* get the current external clock value */
00198 double get_external_clock(VideoState *is)
00199 {
00200     int64_t ti;
00201     ti = av_gettime();
00202     return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
00203 }
00204 
00205 /* get the current master clock value */
00206 double get_master_clock(VideoState *is)
00207 {
00208     double val;
00209 
00210     if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) {
00211         if (is->video_st)
00212             val = get_video_clock(is);
00213         else
00214             val = get_audio_clock(is);
00215     } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) {
00216         if (is->audio_st)
00217             val = get_audio_clock(is);
00218         else
00219             val = get_video_clock(is);
00220     } else {
00221         val = get_external_clock(is);
00222     }
00223     return val;
00224 }
00225 
00226 /* pause or resume the video */
00227 void stream_pause(VideoState *is)
00228 {
00229     is->paused = !is->paused;
00230     if (is->paused) {
00231         is->video_current_pts = get_video_clock(is);
00232     }
00233 }
00234 
00239 int queue_picture(VideoState *is, AVFrame *src_frame, double pts)
00240 {
00241     VideoPicture *vp;
00242     int dst_pix_fmt;
00243     AVPicture pict;
00244     
00245     
00246     
00247 
00248     /* wait until we have space to put a new picture */
00249     SDL_LockMutex(is->pictq_mutex);
00250     while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
00251            !is->videoq.abort_request) {
00252         SDL_CondWait(is->pictq_cond, is->pictq_mutex);
00253            }
00254            SDL_UnlockMutex(is->pictq_mutex);
00255 
00256            if (is->videoq.abort_request)
00257                return -1;
00258 
00259            vp = &is->pictq[is->pictq_windex];
00260 
00261            /* alloc or resize hardware picture buffer */
00262            if (!vp->bmp ||
00263                 vp->width != is->video_st->codec->width ||
00264                 vp->height != is->video_st->codec->height) {
00265                SDL_Event event;
00266 
00267                vp->allocated = 0;
00268 
00269         /* the allocation must be done in the main thread to avoid
00270                locking problems */
00271                event.type = FF_ALLOC_EVENT;
00272                event.user.data1 = is;
00273                SDL_PushEvent(&event);
00274 
00275                /* wait until the picture is allocated */
00276                SDL_LockMutex(is->pictq_mutex);
00277                while (!vp->allocated && !is->videoq.abort_request) {
00278                    SDL_CondWait(is->pictq_cond, is->pictq_mutex);
00279                }
00280                SDL_UnlockMutex(is->pictq_mutex);
00281 
00282                if (is->videoq.abort_request)
00283                    return -1;
00284                 }
00285 
00286                 /* if the frame is not skipped, then display it */
00287                 if (vp->bmp) {
00288                     /* get a pointer on the bitmap */
00289                     SDL_LockYUVOverlay (vp->bmp);
00290 
00291                     dst_pix_fmt = PIX_FMT_YUV420P;
00292                     
00293                     pict.data[0] = vp->bmp->pixels[0];
00294                     pict.data[1] = vp->bmp->pixels[2];
00295                     pict.data[2] = vp->bmp->pixels[1];
00296 
00297                     pict.linesize[0] = vp->bmp->pitches[0];
00298                     pict.linesize[1] = vp->bmp->pitches[2];
00299                     pict.linesize[2] = vp->bmp->pitches[1];
00300                                                    
00301                                         // copy the vp->bmp pixels to some other structure
00302                                         globWidth = is->video_st->codec->width;
00303                                         globHeight = is->video_st->codec->height;
00304                                         globLine0 =pict.linesize[0];
00305                                         globLine1 =pict.linesize[1];
00306                                         globLine2 =pict.linesize[2];
00307                                         
00308                                         // Need only do this alloc once.. 
00309                                         if (!dataR)
00310                                                 dataR = (Uint8*)av_malloc( globLine0 * globHeight);
00311                                         if (!dataG)
00312                                                 dataG = (Uint8*)av_malloc(globLine1 * globHeight);
00313                                         if (!dataB)
00314                                                 dataB = (Uint8*)av_malloc(globLine2 * globHeight);
00315                                         
00316                                         //memcpy( (void*)dataR, (void*)pict.data[0], pict.linesize[0] * globHeight);
00317                                         //memcpy( (void*)dataB, (void*)&pict.data[2], pict.linesize[2]);
00318                                         //memcpy( (void*)dataA, pict.data[3], pict.linesize[3]);
00319                                         //printf("%d %d %d %d\n",pict.linesize[0],pict.linesize[1],pict.linesize[2],pict.linesize[3]);
00320                                         //memcpy( (void*)dataa, &grabPict.data[3], grabPict.linesize[3]);                
00321                     // Original below
00322                     // RLR Here ??
00323                     //img_convert(&pict, PIX_FMT_RGBA32,
00324                                //(AVPicture *)src_frame, is->video_st->codec->pix_fmt,
00325                                 //is->video_st->codec->width, is->video_st->codec->height);
00326                        
00327                     img_convert(&pict, dst_pix_fmt,
00328                                (AVPicture *)src_frame, is->video_st->codec->pix_fmt,
00329                                  is->video_st->codec->width, is->video_st->codec->height);
00330                         
00331                         memcpy( dataR, vp->bmp->pixels[0], globLine0 * globHeight);
00332                                         memcpy( dataG, vp->bmp->pixels[2], globLine2 * globHeight);
00333                                         memcpy( dataB, vp->bmp->pixels[1], globLine1 * globHeight);                                     
00334                                                                         
00335                                         //printf("fmt %x\n",vp->bmp->format);
00336                     /* update the bitmap content */
00337                     SDL_UnlockYUVOverlay(vp->bmp);
00338 
00339                     vp->pts = pts;
00340 
00341                     /* now we can update the picture count */
00342                     if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
00343                         is->pictq_windex = 0;
00344                     SDL_LockMutex(is->pictq_mutex);
00345                     is->pictq_size++;
00346                     SDL_UnlockMutex(is->pictq_mutex);
00347                 }
00348                 return 0;
00349 }
00350 
00355 int output_picture2(VideoState *is, AVFrame *src_frame, double pts1)
00356 {
00357     double frame_delay, pts;
00358 
00359     pts = pts1;
00360 
00361     if (pts != 0) {
00362         /* update video clock with pts, if present */
00363         is->video_clock = pts;
00364     } else {
00365         pts = is->video_clock;
00366     }
00367     /* update video clock for next frame */
00368     frame_delay = av_q2d(is->video_st->codec->time_base);
00369     /* for MPEG2, the frame can be repeated, so we update the
00370     clock accordingly */
00371     frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
00372     is->video_clock += frame_delay;
00373     return queue_picture(is, src_frame, pts);
00374 }
00375 
00376 int video_thread(void *arg)
00377 {
00378     VideoState *is = (VideoState*)arg;
00379     AVPacket pkt1, *pkt = &pkt1;
00380     int len1, got_picture;
00381     AVFrame *frame= avcodec_alloc_frame();
00382     double pts;
00383 
00384     for(;;) {
00385         while (is->paused && !is->videoq.abort_request) {
00386             SDL_Delay(10);
00387         }
00388         if (packet_queue_get(&is->videoq, pkt, 1) < 0)
00389             break;
00390         /* NOTE: ipts is the PTS of the _first_ picture beginning in
00391         this packet, if any */
00392         pts = 0;
00393         if (pkt->dts != AV_NOPTS_VALUE)
00394             pts = av_q2d(is->video_st->time_base)*pkt->dts;
00395 
00396         SDL_LockMutex(is->video_decoder_mutex);
00397         len1 = avcodec_decode_video(is->video_st->codec,
00398                                     frame, &got_picture,
00399                                     pkt->data, pkt->size);
00400         SDL_UnlockMutex(is->video_decoder_mutex);
00401 
00402         if (got_picture) {
00403             if (output_picture2(is, frame, pts) < 0)
00404                 goto the_end;
00405         }
00406         av_free_packet(pkt);
00407         if (step)
00408             if (cur_stream)
00409                 stream_pause(cur_stream);
00410     }
00411  the_end:
00412          av_free(frame);
00413  return 0;
00414 }
00415 
00416 int subtitle_thread(void *arg)
00417 {
00418     VideoState *is = (VideoState*)arg;
00419     SubPicture *sp;
00420     AVPacket pkt1, *pkt = &pkt1;
00421     int len1, got_subtitle;
00422     double pts;
00423     int i, j;
00424     int r, g, b, y, u, v, a;
00425 
00426     for(;;) {
00427         while (is->paused && !is->subtitleq.abort_request) {
00428             SDL_Delay(10);
00429         }
00430         if (packet_queue_get(&is->subtitleq, pkt, 1) < 0)
00431             break;
00432 
00433         SDL_LockMutex(is->subpq_mutex);
00434         while (is->subpq_size >= SUBPICTURE_QUEUE_SIZE &&
00435                !is->subtitleq.abort_request) {
00436             SDL_CondWait(is->subpq_cond, is->subpq_mutex);
00437                }
00438                SDL_UnlockMutex(is->subpq_mutex);
00439 
00440                if (is->subtitleq.abort_request)
00441                    goto the_end;
00442 
00443                sp = &is->subpq[is->subpq_windex];
00444 
00445        /* NOTE: ipts is the PTS of the _first_ picture beginning in
00446                this packet, if any */
00447                pts = 0;
00448                if (pkt->pts != AV_NOPTS_VALUE)
00449                    pts = av_q2d(is->subtitle_st->time_base)*pkt->pts;
00450 
00451                SDL_LockMutex(is->subtitle_decoder_mutex);
00452                len1 = avcodec_decode_subtitle(is->subtitle_st->codec,
00453                                               &sp->sub, &got_subtitle,
00454                                               pkt->data, pkt->size);
00455                SDL_UnlockMutex(is->subtitle_decoder_mutex);
00456 //            if (len1 < 0)
00457 //                break;
00458                if (got_subtitle && sp->sub.format == 0) {
00459                    sp->pts = pts;
00460 
00461                    for (i = 0; i < sp->sub.num_rects; i++)
00462                    {
00463                        for (j = 0; j < sp->sub.rects[i].nb_colors; j++)
00464                        {
00465                            RGBA_IN(r, g, b, a, sp->sub.rects[i].rgba_palette + j);
00466                            y = RGB_TO_Y_CCIR(r, g, b);
00467                            u = RGB_TO_U_CCIR(r, g, b, 0);
00468                            v = RGB_TO_V_CCIR(r, g, b, 0);
00469                            YUVA_OUT(sp->sub.rects[i].rgba_palette + j, y, u, v, a);
00470                        }
00471                    }
00472 
00473                    /* now we can update the picture count */
00474                    if (++is->subpq_windex == SUBPICTURE_QUEUE_SIZE)
00475                        is->subpq_windex = 0;
00476                    SDL_LockMutex(is->subpq_mutex);
00477                    is->subpq_size++;
00478                    SDL_UnlockMutex(is->subpq_mutex);
00479                }
00480                av_free_packet(pkt);
00481     }
00482  the_end:
00483          return 0;
00484 }
00485 
00486 /* copy samples for viewing in editor window */
00487 void update_sample_display(VideoState *is, short *samples, int samples_size)
00488 {
00489     int size, len, channels;
00490 
00491     channels = is->audio_st->codec->channels;
00492 
00493     size = samples_size / sizeof(short);
00494     while (size > 0) {
00495         len = SAMPLE_ARRAY_SIZE - is->sample_array_index;
00496         if (len > size)
00497             len = size;
00498         memcpy(is->sample_array + is->sample_array_index, samples, len * sizeof(short));
00499         samples += len;
00500         is->sample_array_index += len;
00501         if (is->sample_array_index >= SAMPLE_ARRAY_SIZE)
00502             is->sample_array_index = 0;
00503         size -= len;
00504     }
00505 }
00506 
00507 /* return the new audio buffer size (samples can be added or deleted
00508    to get better sync if video or external master clock) */
00509 int synchronize_audio(VideoState *is, short *samples,int samples_size1, double pts)
00510 {
00511     int n, samples_size;
00512     double ref_clock;
00513 
00514     n = 2 * is->audio_st->codec->channels;
00515     samples_size = samples_size1;
00516 
00517     /* if not master, then we try to remove or add samples to correct the clock */
00518     if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
00519           is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
00520         double diff, avg_diff;
00521         int wanted_size, min_size, max_size, nb_samples;
00522 
00523         ref_clock = get_master_clock(is);
00524         diff = get_audio_clock(is) - ref_clock;
00525 
00526         if (diff < AV_NOSYNC_THRESHOLD) {
00527             is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
00528             if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
00529                 /* not enough measures to have a correct estimate */
00530                 is->audio_diff_avg_count++;
00531             } else {
00532                 /* estimate the A-V difference */
00533                 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
00534 
00535                 if (fabs(avg_diff) >= is->audio_diff_threshold) {
00536                     wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
00537                     nb_samples = samples_size / n;
00538 
00539                     min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
00540                     max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
00541                     if (wanted_size < min_size)
00542                         wanted_size = min_size;
00543                     else if (wanted_size > max_size)
00544                         wanted_size = max_size;
00545 
00546                     /* add or remove samples to correction the synchro */
00547                     if (wanted_size < samples_size) {
00548                         /* remove samples */
00549                         samples_size = wanted_size;
00550                     } else if (wanted_size > samples_size) {
00551                         uint8_t *samples_end, *q;
00552                         int nb;
00553 
00554                         /* add samples */
00555                         nb = (samples_size - wanted_size);
00556                         samples_end = (uint8_t *)samples + samples_size - n;
00557                         q = samples_end + n;
00558                         while (nb > 0) {
00559                             memcpy(q, samples_end, n);
00560                             q += n;
00561                             nb -= n;
00562                         }
00563                         samples_size = wanted_size;
00564                     }
00565                 }
00566             }
00567         } else {
00568             /* too big difference : may be initial PTS errors, so
00569             reset A-V filter */
00570             is->audio_diff_avg_count = 0;
00571             is->audio_diff_cum = 0;
00572         }
00573           }
00574           return samples_size;
00575 }
00576 
00577 /* decode one audio frame and returns its uncompressed size */
00578 int audio_decode_frame(VideoState *is, uint8_t *audio_buf, double *pts_ptr)
00579 {
00580     AVPacket *pkt = &is->audio_pkt;
00581     int n, len1, data_size;
00582     double pts;
00583 
00584     for(;;) {
00585         /* NOTE: the audio packet can contain several frames */
00586         while (is->audio_pkt_size > 0) {
00587             SDL_LockMutex(is->audio_decoder_mutex);
00588             len1 = avcodec_decode_audio(is->audio_st->codec,
00589                                         (int16_t *)audio_buf, &data_size,
00590                                         is->audio_pkt_data, is->audio_pkt_size);
00591             SDL_UnlockMutex(is->audio_decoder_mutex);
00592             if (len1 < 0) {
00593                 /* if error, we skip the frame */
00594                 is->audio_pkt_size = 0;
00595                 break;
00596             }
00597 
00598             is->audio_pkt_data += len1;
00599             is->audio_pkt_size -= len1;
00600             if (data_size <= 0)
00601                 continue;
00602             /* if no pts, then compute it */
00603             pts = is->audio_clock;
00604             *pts_ptr = pts;
00605             n = 2 * is->audio_st->codec->channels;
00606             is->audio_clock += (double)data_size /
00607                     (double)(n * is->audio_st->codec->sample_rate);
00608 #if defined(DEBUG_SYNC)
00609 {
00610     static double last_clock;
00611     printf("audio: delay=%0.3f clock=%0.3f pts=%0.3f\n",
00612            is->audio_clock - last_clock,
00613            is->audio_clock, pts);
00614     last_clock = is->audio_clock;
00615 }
00616 #endif
00617             return data_size;
00618         }
00619 
00620         /* free the current packet */
00621         if (pkt->data)
00622             av_free_packet(pkt);
00623 
00624         if (is->paused || is->audioq.abort_request) {
00625             return -1;
00626         }
00627 
00628         /* read next packet */
00629         if (packet_queue_get(&is->audioq, pkt, 1) < 0)
00630             return -1;
00631         is->audio_pkt_data = pkt->data;
00632         is->audio_pkt_size = pkt->size;
00633 
00634         /* if update the audio clock with the pts */
00635         if (pkt->pts != AV_NOPTS_VALUE) {
00636             is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
00637         }
00638     }
00639 }
00640 
00641 /* get the current audio output buffer size, in samples. With SDL, we
00642    cannot have a precise information */
00643 int audio_write_get_buf_size(VideoState *is)
00644 {
00645     return is->audio_hw_buf_size - is->audio_buf_index;
00646 }
00647 
00648 /* prepare a new audio buffer */
00649 void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
00650 {
00651     VideoState *is = (VideoState*)opaque;
00652     int audio_size, len1;
00653     double pts;
00654 
00655     audio_callback_time = av_gettime();
00656 
00657     while (len > 0) {
00658         if (is->audio_buf_index >= is->audio_buf_size) {
00659             audio_size = audio_decode_frame(is, is->audio_buf, &pts);
00660             if (audio_size < 0) {
00661                 /* if error, just output silence */
00662                 is->audio_buf_size = 1024;
00663                 memset(is->audio_buf, 0, is->audio_buf_size);
00664             } else {
00665                 if (is->show_audio)
00666                     update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
00667                 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
00668                                                pts);
00669                 is->audio_buf_size = audio_size;
00670             }
00671             is->audio_buf_index = 0;
00672         }
00673         len1 = is->audio_buf_size - is->audio_buf_index;
00674         if (len1 > len)
00675             len1 = len;
00676         memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
00677         len -= len1;
00678         stream += len1;
00679         is->audio_buf_index += len1;
00680     }
00681 }
00682 
00683 
00684 /* open a given stream. Return 0 if OK */
00685 int stream_component_open(VideoState *is, int stream_index)
00686 {
00687     AVFormatContext *ic = is->ic;
00688     AVCodecContext *enc;
00689     AVCodec *codec;
00690     SDL_AudioSpec wanted_spec, spec;
00691 
00692     if (stream_index < 0 || stream_index >= ic->nb_streams)
00693         return -1;
00694     enc = ic->streams[stream_index]->codec;
00695 
00696     /* prepare audio output */
00697     if (enc->codec_type == CODEC_TYPE_AUDIO) {
00698         wanted_spec.freq = enc->sample_rate;
00699         wanted_spec.format = AUDIO_S16SYS;
00700         /* hack for AC3. XXX: suppress that */
00701         if (enc->channels > 2)
00702             enc->channels = 2;
00703         wanted_spec.channels = enc->channels;
00704         wanted_spec.silence = 0;
00705         wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
00706         wanted_spec.callback = sdl_audio_callback;
00707         wanted_spec.userdata = is;
00708         if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
00709             fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
00710             return -1;
00711         }
00712         is->audio_hw_buf_size = spec.size;
00713     }
00714 
00715     codec = avcodec_find_decoder(enc->codec_id);
00716     enc->debug_mv = debug_mv;
00717     enc->debug = debug;
00718     if(debug)
00719         av_log_set_level(AV_LOG_DEBUG);
00720     enc->workaround_bugs = workaround_bugs;
00721     enc->lowres = lowres;
00722     if(lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
00723     enc->idct_algo= idct;
00724     if(fast) enc->flags2 |= CODEC_FLAG2_FAST;
00725     enc->skip_frame= skip_frame;
00726     enc->skip_idct= skip_idct;
00727     enc->skip_loop_filter= skip_loop_filter;
00728     enc->error_resilience= error_resilience;
00729     enc->error_concealment= error_concealment;
00730     if (!codec ||
00731          avcodec_open(enc, codec) < 0)
00732         return -1;
00733 #if defined(HAVE_THREADS)
00734     if(thread_count>1)
00735         avcodec_thread_init(enc, thread_count);
00736 #endif
00737     enc->thread_count= thread_count;
00738     switch(enc->codec_type) {
00739         case CODEC_TYPE_AUDIO:
00740             is->audio_stream = stream_index;
00741             is->audio_st = ic->streams[stream_index];
00742             is->audio_buf_size = 0;
00743             is->audio_buf_index = 0;
00744 
00745             /* init averaging filter */
00746             is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
00747             is->audio_diff_avg_count = 0;
00748         /* since we do not have a precise anough audio fifo fullness,
00749             we correct audio sync only if larger than this threshold */
00750             is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / enc->sample_rate;
00751 
00752             memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
00753             packet_queue_init(&is->audioq);
00754             SDL_PauseAudio(0);
00755             break;
00756         case CODEC_TYPE_VIDEO:
00757             is->video_stream = stream_index;
00758             is->video_st = ic->streams[stream_index];
00759 
00760             is->frame_last_delay = 40e-3;
00761             is->frame_timer = (double)av_gettime() / 1000000.0;
00762             is->video_current_pts_time = av_gettime();
00763 
00764             packet_queue_init(&is->videoq);
00765             is->video_tid = SDL_CreateThread(video_thread, is);
00766             break;
00767         case CODEC_TYPE_SUBTITLE:
00768             is->subtitle_stream = stream_index;
00769             is->subtitle_st = ic->streams[stream_index];
00770             packet_queue_init(&is->subtitleq);
00771 
00772             is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
00773             break;
00774         default:
00775             break;
00776     }
00777     return 0;
00778 }
00779 
00780 void stream_component_close(VideoState *is, int stream_index)
00781 {
00782     AVFormatContext *ic = is->ic;
00783     AVCodecContext *enc;
00784 
00785     if (stream_index < 0 || stream_index >= ic->nb_streams)
00786         return;
00787     enc = ic->streams[stream_index]->codec;
00788 
00789     switch(enc->codec_type) {
00790         case CODEC_TYPE_AUDIO:
00791             packet_queue_abort(&is->audioq);
00792 
00793             SDL_CloseAudio();
00794 
00795             packet_queue_end(&is->audioq);
00796             break;
00797         case CODEC_TYPE_VIDEO:
00798             packet_queue_abort(&is->videoq);
00799 
00800         /* note: we also signal this mutex to make sure we deblock the
00801             video thread in all cases */
00802             SDL_LockMutex(is->pictq_mutex);
00803             SDL_CondSignal(is->pictq_cond);
00804             SDL_UnlockMutex(is->pictq_mutex);
00805 
00806             SDL_WaitThread(is->video_tid, NULL);
00807 
00808             packet_queue_end(&is->videoq);
00809             break;
00810         case CODEC_TYPE_SUBTITLE:
00811             packet_queue_abort(&is->subtitleq);
00812 
00813         /* note: we also signal this mutex to make sure we deblock the
00814             video thread in all cases */
00815             SDL_LockMutex(is->subpq_mutex);
00816             is->subtitle_stream_changed = 1;
00817 
00818             SDL_CondSignal(is->subpq_cond);
00819             SDL_UnlockMutex(is->subpq_mutex);
00820 
00821             SDL_WaitThread(is->subtitle_tid, NULL);
00822 
00823             packet_queue_end(&is->subtitleq);
00824             break;
00825         default:
00826             break;
00827     }
00828 
00829     avcodec_close(enc);
00830     switch(enc->codec_type) {
00831         case CODEC_TYPE_AUDIO:
00832             is->audio_st = NULL;
00833             is->audio_stream = -1;
00834             break;
00835         case CODEC_TYPE_VIDEO:
00836             is->video_st = NULL;
00837             is->video_stream = -1;
00838             break;
00839         case CODEC_TYPE_SUBTITLE:
00840             is->subtitle_st = NULL;
00841             is->subtitle_stream = -1;
00842             break;
00843         default:
00844             break;
00845     }
00846 }
00847 
00848 void dump_stream_info(AVFormatContext *s)
00849 {
00850     if (s->track != 0)
00851         fprintf(stderr, "Track: %d\n", s->track);
00852     if (s->title[0] != '\0')
00853         fprintf(stderr, "Title: %s\n", s->title);
00854     if (s->author[0] != '\0')
00855         fprintf(stderr, "Author: %s\n", s->author);
00856     if (s->album[0] != '\0')
00857         fprintf(stderr, "Album: %s\n", s->album);
00858     if (s->year != 0)
00859         fprintf(stderr, "Year: %d\n", s->year);
00860     if (s->genre[0] != '\0')
00861         fprintf(stderr, "Genre: %s\n", s->genre);
00862 }
00863 
00864 int decode_interrupt_cb(void)
00865 {
00866     return (global_video_state && global_video_state->abort_request);
00867 }
00868 
00869 /* this thread gets the stream from the disk or the network */
00870 int decode_thread(void *arg)
00871 {
00872     VideoState *is = (VideoState*)arg;
00873     AVFormatContext *ic;
00874     int err, i, ret, video_index, audio_index, use_play;
00875     AVPacket pkt1, *pkt = &pkt1;
00876     AVFormatParameters params, *ap = &params;
00877 
00878     video_index = -1;
00879     audio_index = -1;
00880     is->video_stream = -1;
00881     is->audio_stream = -1;
00882     is->subtitle_stream = -1;
00883 
00884     global_video_state = is;
00885     url_set_interrupt_cb(decode_interrupt_cb);
00886 
00887     memset(ap, 0, sizeof(*ap));
00888     ap->image_format = image_format;
00889     ap->initial_pause = 1; /* we force a pause when starting an RTSP
00890     stream */
00891 
00892     err = av_open_input_file(&ic, is->filename, is->iformat, 0, ap);
00893     if (err < 0) {
00894         //print_error(is->filename, err);
00895         ret = -1;
00896         goto fail;
00897     }
00898     is->ic = ic;
00899 //#ifdef CONFIG_NETWORK
00900   //  use_play = (ic->iformat == &rtsp_demux);
00901 //#else
00902     use_play = 0;
00903 //#endif
00904 
00905     if(genpts)
00906         ic->flags |= AVFMT_FLAG_GENPTS;
00907 
00908     if (!use_play) {
00909         err = av_find_stream_info(ic);
00910         if (err < 0) {
00911             fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
00912             ret = -1;
00913             goto fail;
00914         }
00915         ic->pb.eof_reached= 0; //FIXME hack, ffplay maybe shouldnt use url_feof() to test for the end
00916     }
00917 
00918     /* if seeking requested, we execute it */
00919     if (start_time != AV_NOPTS_VALUE) {
00920         int64_t timestamp;
00921 
00922         timestamp = start_time;
00923         /* add the stream start time */
00924         if (ic->start_time != AV_NOPTS_VALUE)
00925             timestamp += ic->start_time;
00926         ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD);
00927         if (ret < 0) {
00928             fprintf(stderr, "%s: could not seek to position %0.3f\n",
00929                     is->filename, (double)timestamp / AV_TIME_BASE);
00930         }
00931     }
00932 
00933     /* now we can begin to play (RTSP stream only) */
00934     av_read_play(ic);
00935 
00936     if (use_play) {
00937         err = av_find_stream_info(ic);
00938         if (err < 0) {
00939             fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
00940             ret = -1;
00941             goto fail;
00942         }
00943     }
00944 
00945     for(i = 0; i < ic->nb_streams; i++) {
00946         AVCodecContext *enc = ic->streams[i]->codec;
00947         switch(enc->codec_type) {
00948             case CODEC_TYPE_AUDIO:
00949                 if (audio_index < 0 && !audio_disable)
00950                     audio_index = i;
00951                 break;
00952             case CODEC_TYPE_VIDEO:
00953                 if (video_index < 0 && !video_disable)
00954                     video_index = i;
00955                 break;
00956             default:
00957                 break;
00958         }
00959     }
00960     if (show_status) {
00961         dump_format(ic, 0, is->filename, 0);
00962         dump_stream_info(ic);
00963     }
00964 
00965     /* open the streams */
00966     if (audio_index >= 0) {
00967         stream_component_open(is, audio_index);
00968     }
00969 
00970     if (video_index >= 0) {
00971         stream_component_open(is, video_index);
00972     } else {
00973         if (!display_disable)
00974             is->show_audio = 1;
00975     }
00976 
00977     if (is->video_stream < 0 && is->audio_stream < 0) {
00978         fprintf(stderr, "%s: could not open codecs\n", is->filename);
00979         ret = -1;
00980         goto fail;
00981     }
00982 
00983     for(;;) {
00984         if (is->abort_request)
00985             break;
00986 #ifdef CONFIG_NETWORK
00987         if (is->paused != is->last_paused) {
00988     is->last_paused = is->paused;
00989     if (is->paused)
00990         av_read_pause(ic);
00991     else
00992         av_read_play(ic);
00993         }
00994         //if (is->paused && ic->iformat == &rtsp_demux) {
00995             /* wait 10 ms to avoid trying to get another packet */
00996             /* XXX: horrible */
00997         //    SDL_Delay(10);
00998         //    continue;
00999         //}
01000 #endif
01001         if (is->seek_req) {
01002     /* XXX: must lock decoder threads */
01003     SDL_LockMutex(is->video_decoder_mutex);
01004     SDL_LockMutex(is->audio_decoder_mutex);
01005     SDL_LockMutex(is->subtitle_decoder_mutex);
01006     ret = av_seek_frame(is->ic, -1, is->seek_pos, is->seek_flags);
01007     if (ret < 0) {
01008         fprintf(stderr, "%s: error while seeking\n", is->ic->filename);
01009     }else{
01010         if (is->audio_stream >= 0) {
01011             packet_queue_flush(&is->audioq);
01012         }
01013         if (is->subtitle_stream >= 0) {
01014             packet_queue_flush(&is->subtitleq);
01015         }
01016         if (is->video_stream >= 0) {
01017             packet_queue_flush(&is->videoq);
01018             avcodec_flush_buffers(ic->streams[video_index]->codec);
01019         }
01020     }
01021     SDL_UnlockMutex(is->subtitle_decoder_mutex);
01022     SDL_UnlockMutex(is->audio_decoder_mutex);
01023     SDL_UnlockMutex(is->video_decoder_mutex);
01024     is->seek_req = 0;
01025         }
01026 
01027         /* if the queue are full, no need to read more */
01028         if (is->audioq.size > MAX_AUDIOQ_SIZE ||
01029             is->videoq.size > MAX_VIDEOQ_SIZE ||
01030             is->subtitleq.size > MAX_SUBTITLEQ_SIZE ||
01031             url_feof(&ic->pb)) {
01032             /* wait 10 ms */
01033             SDL_Delay(10);
01034             continue;
01035             }
01036             ret = av_read_frame(ic, pkt);
01037             if (ret < 0) {
01038                 if (url_ferror(&ic->pb) == 0) {
01039                     SDL_Delay(100); /* wait for user event */
01040                     continue;
01041                 } else
01042                     break;
01043             }
01044             if (pkt->stream_index == is->audio_stream) {
01045                 packet_queue_put(&is->audioq, pkt);
01046             } else if (pkt->stream_index == is->video_stream) {
01047                 packet_queue_put(&is->videoq, pkt);
01048             } else if (pkt->stream_index == is->subtitle_stream) {
01049                 packet_queue_put(&is->subtitleq, pkt);
01050             } else {
01051                 av_free_packet(pkt);
01052             }
01053     }
01054     /* wait until the end */
01055     while (!is->abort_request) {
01056         SDL_Delay(100);
01057     }
01058 
01059     ret = 0;
01060  fail:
01061          /* disable interrupting */
01062          global_video_state = NULL;
01063 
01064  /* close each stream */
01065  if (is->audio_stream >= 0)
01066      stream_component_close(is, is->audio_stream);
01067  if (is->video_stream >= 0)
01068      stream_component_close(is, is->video_stream);
01069  if (is->subtitle_stream >= 0)
01070      stream_component_close(is, is->subtitle_stream);
01071  if (is->ic) {
01072      av_close_input_file(is->ic);
01073      is->ic = NULL; /* safety */
01074  }
01075  url_set_interrupt_cb(NULL);
01076 
01077  if (ret != 0) {
01078      SDL_Event event;
01079 
01080      event.type = FF_QUIT_EVENT;
01081      event.user.data1 = is;
01082      SDL_PushEvent(&event);
01083  }
01084  return 0;
01085 }
01086 
01087 #endif /*QTFFUTIL_H_*/

Generated on Thu Aug 17 12:14:56 2006 for VisualODF by  doxygen 1.4.7