Exemple #1
1
int decode_thread(void *arg) {
// 上半部分的函数没什么新东西;它的工作就是打开文件和找到视频流和音频流的索引。
// 唯一不同的地方是把格式内容保存到大结构体中。当找到流后,调用另一个将要定义的函数 stream_component_open()。
// 这是一个一般的分离的方法,自从我们设置很多相似的视频和音频解码的代码,我们通过编写这个函数来重用它们。
  VideoState *is = (VideoState *)arg;
  AVFormatContext *pFormatCtx = NULL;
  AVPacket pkt1, *packet = &pkt1;
  // http://www.ffmpeg.org/doxygen/3.1/group__lavu__dict.html#details
  AVDictionary *io_dict = NULL; // AVDictionary 元数据,Simple key:value store.
  // http://www.ffmpeg.org/doxygen/3.1/structAVIOInterruptCB.html#details
  AVIOInterruptCB callback;     // Callback for checking whether to abort blocking functions.

  int video_index = -1;
  int audio_index = -1;
  int i;

  is->videoStream=-1;
  is->audioStream=-1;

  global_video_state = is;
  // will interrupt blocking functions if we quit!
  callback.callback = decode_interrupt_cb;
  callback.opaque = is;
  // http://www.ffmpeg.org/doxygen/3.1/aviobuf_8c.html#ae8589aae955d16ca228b6b9d66ced33d
  // 使用is->filename的内容初始化is->io_context,用于管理文件的读写
  if (avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict))
  {
    fprintf(stderr, "Unable to open I/O for %s\n", is->filename);
    return -1;
  }

  // 从传入的第二个参数获得文件路径,这个函数会读取文件头信息,并把信息保存在 pFormatCtx 结构体当中。
  // 这个函数后面两个参数分别是: 指定文件格式、格式化选项,当我们设置为 NULL 或 0 时,libavformat 会自动完成这些工作。
  if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL)!=0)
    return -1; // Couldn't open file

  is->pFormatCtx = pFormatCtx;

  // Retrieve stream information
  // 得到流信息
  if(avformat_find_stream_info(pFormatCtx, NULL)<0)
    return -1; // Couldn't find stream information

  // Dump information about file onto standard error
  // 这个函数填充了 pFormatCtx->streams 流信息, 可以通过 dump_format 把信息打印出来:
  av_dump_format(pFormatCtx, 0, is->filename, 0);

  // 查找一个音频和视频流
  for(i=0; i<pFormatCtx->nb_streams; i++) {
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
       video_index < 0) {
      video_index=i;
    }
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
       audio_index < 0) {
      audio_index=i;
    }
  }

  // stream_component_open()函数的作用是找到解码器,设置音频参数,保存重要信息到大结构体中,然后启动音频和视频线程。
  if(audio_index >= 0) {
    stream_component_open(is, audio_index);
  }
  if(video_index >= 0) {
    stream_component_open(is, video_index);
  }

  if(is->videoStream < 0 || is->audioStream < 0) {
    fprintf(stderr, "%s: could not open codecs\n", is->filename);
    goto fail;
  }

  // main decode loop
  // 上面都是打开文件和找到视频流和音频流的索引等工作,下面才是主循环
  for(;;) {
    if(is->quit) {
      break;  // 控制循环是否退出
    }
    // seek stuff goes here
    if(is->audioq.size > MAX_AUDIOQ_SIZE ||
       is->videoq.size > MAX_VIDEOQ_SIZE) {
      SDL_Delay(10);
      continue;
    }
    if(av_read_frame(is->pFormatCtx, packet) < 0) {
      if(is->pFormatCtx->pb->error == 0) {
	      SDL_Delay(100); /* no error; wait for user input */
	      continue;
      } else {
	      break;
      }
    }
    // Is this a packet from the video stream?
    if(packet->stream_index == is->videoStream) {
      packet_queue_put(&is->videoq, packet);
    } else if(packet->stream_index == is->audioStream) {
      packet_queue_put(&is->audioq, packet);
    } else {
      av_free_packet(packet);
    }
  }
  /* all done - wait for it */
  while(!is->quit) {
    SDL_Delay(100);
  }

 fail:
  {
    SDL_Event event;
    event.type = FF_QUIT_EVENT;
    event.user.data1 = is;
    SDL_PushEvent(&event);
  }
  return 0;
}
Exemple #2
0
static int startread(sox_format_t * ft)
{
  priv_t * ffmpeg = (priv_t *)ft->priv;
  AVFormatParameters params;
  int ret;
  int i;

  ffmpeg->audio_buf_raw = lsx_calloc(1, (size_t)AVCODEC_MAX_AUDIO_FRAME_SIZE + 32);
  ffmpeg->audio_buf_aligned = ALIGN16(ffmpeg->audio_buf_raw);

  /* Signal audio stream not found */
  ffmpeg->audio_index = -1;

  /* register all CODECs, demux and protocols */
  av_register_all();

  /* Open file and get format */
  memset(&params, 0, sizeof(params));
  if ((ret = av_open_input_file(&ffmpeg->ctxt, ft->filename, NULL, 0, &params)) < 0) {
    lsx_fail("ffmpeg cannot open file for reading: %s (code %d)", ft->filename, ret);
    return SOX_EOF;
  }

  /* Get CODEC parameters */
  if ((ret = av_find_stream_info(ffmpeg->ctxt)) < 0) {
    lsx_fail("ffmpeg could not find CODEC parameters for %s", ft->filename);
    return SOX_EOF;
  }

  /* Now we can begin to play (RTSP stream only) */
  av_read_play(ffmpeg->ctxt);

  /* Find audio stream (FIXME: allow different stream to be selected) */
  for (i = 0; (unsigned)i < ffmpeg->ctxt->nb_streams; i++) {
    AVCodecContext *enc = ffmpeg->ctxt->streams[i]->codec;
    if (enc->codec_type == CODEC_TYPE_AUDIO && ffmpeg->audio_index < 0) {
      ffmpeg->audio_index = i;
      break;
    }
  }

  /* Open the stream */
  if (ffmpeg->audio_index < 0 ||
      stream_component_open(ffmpeg, ffmpeg->audio_index) < 0 ||
      ffmpeg->audio_stream < 0) {
    lsx_fail("ffmpeg could not open CODECs for %s", ft->filename);
    return SOX_EOF;
  }

  /* Copy format info */
  ft->signal.rate = ffmpeg->audio_st->codec->sample_rate;
  ft->encoding.bits_per_sample = 16;
  ft->encoding.encoding = SOX_ENCODING_SIGN2;
  ft->signal.channels = ffmpeg->audio_st->codec->channels;
  ft->signal.length = 0; /* Currently we can't seek; no idea how to get this
		     info from ffmpeg anyway (in time, yes, but not in
		     samples); but ffmpeg *can* seek */

  return SOX_SUCCESS;
}
int decode_thread(void *arg) {

    VideoState *is = (VideoState *)arg;
    AVFormatContext *pFormatCtx = NULL;
    AVPacket pkt1, *packet = &pkt1;

    AVDictionary *io_dict = NULL;
    AVIOInterruptCB callback;

    int video_index = -1;
    int audio_index = -1;
    int i;

    is->videoStream = -1;
    is->audioStream = -1;
    is->audio_need_resample = 0;

    global_video_state = is;
    // will interrupt blocking functions if we quit!
    callback.callback = decode_interrupt_cb;
    callback.opaque = is;

    if(avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict)) {
        fprintf(stderr, "Unable to open I/O for %s\n", is->filename);
        return -1;
    }

    // Open video file
    if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL) != 0) {
        return -1;    // Couldn't open file
    }

    is->pFormatCtx = pFormatCtx;

    // Retrieve stream information
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        return -1;    // Couldn't find stream information
    }

    // Dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, is->filename, 0);

    // Find the first video stream
    for(i = 0; i < pFormatCtx->nb_streams; i++) {
        if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
                video_index < 0) {
            video_index = i;
        }

        if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
                audio_index < 0) {
            audio_index = i;
        }
    }

    if(audio_index >= 0) {
        stream_component_open(is, audio_index);
    }

    if(video_index >= 0) {
        stream_component_open(is, video_index);
    }

    if(is->videoStream < 0 && is->audioStream < 0) {
        fprintf(stderr, "%s: could not open codecs\n", is->filename);
        goto fail;
    }

#ifdef __RESAMPLER__

    if( audio_index >= 0
            && pFormatCtx->streams[audio_index]->codec->sample_fmt != AV_SAMPLE_FMT_S16) {
        is->audio_need_resample = 1;
        is->pResampledOut = NULL;
        is->pSwrCtx = NULL;

        printf("Configure resampler: ");

#ifdef __LIBAVRESAMPLE__
        printf("libAvResample\n");
        is->pSwrCtx = avresample_alloc_context();
#endif

#ifdef __LIBSWRESAMPLE__
        printf("libSwResample\n");
        is->pSwrCtx = swr_alloc();
#endif

        // Some MP3/WAV don't tell this so make assumtion that
        // They are stereo not 5.1
        if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0
                && pFormatCtx->streams[audio_index]->codec->channels == 2) {
            pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO;

        } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0
                   && pFormatCtx->streams[audio_index]->codec->channels == 1) {
            pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_MONO;

        } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0
                   && pFormatCtx->streams[audio_index]->codec->channels == 0) {
            pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO;
            pFormatCtx->streams[audio_index]->codec->channels = 2;
        }

        av_opt_set_int(is->pSwrCtx, "in_channel_layout",
                       pFormatCtx->streams[audio_index]->codec->channel_layout, 0);
        av_opt_set_int(is->pSwrCtx, "in_sample_fmt",
                       pFormatCtx->streams[audio_index]->codec->sample_fmt, 0);
        av_opt_set_int(is->pSwrCtx, "in_sample_rate",
                       pFormatCtx->streams[audio_index]->codec->sample_rate, 0);

        av_opt_set_int(is->pSwrCtx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
        av_opt_set_int(is->pSwrCtx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
        av_opt_set_int(is->pSwrCtx, "out_sample_rate", 44100, 0);

#ifdef __LIBAVRESAMPLE__

        if (avresample_open(is->pSwrCtx) < 0) {
#else

        if (swr_init(is->pSwrCtx) < 0) {
#endif
            fprintf(stderr, " ERROR!! From Samplert: %d Hz Sample format: %s\n",
                    pFormatCtx->streams[audio_index]->codec->sample_rate,
                    av_get_sample_fmt_name(pFormatCtx->streams[audio_index]->codec->sample_fmt));
            fprintf(stderr, "         To 44100 Sample format: s16\n");
            is->audio_need_resample = 0;
            is->pSwrCtx = NULL;;
        }

    }

#endif

    // main decode loop

    for(;;) {
        if(is->quit) {
            break;
        }

        // seek stuff goes here
        if(is->seek_req) {
            int stream_index = -1;
            int64_t seek_target = is->seek_pos;

            if(is->videoStream >= 0) {
                stream_index = is->videoStream;

            } else if(is->audioStream >= 0) {
                stream_index = is->audioStream;
            }

            if(stream_index >= 0) {
                seek_target = av_rescale_q(seek_target, AV_TIME_BASE_Q, pFormatCtx->streams[stream_index]->time_base);
            }

            if(av_seek_frame(is->pFormatCtx, stream_index, seek_target, is->seek_flags) < 0) {
                fprintf(stderr, "%s: error while seeking\n", is->pFormatCtx->filename);

            } else {
                if(is->audioStream >= 0) {
                    packet_queue_flush(&is->audioq);
                    packet_queue_put(&is->audioq, &flush_pkt);
                }

                if(is->videoStream >= 0) {
                    packet_queue_flush(&is->videoq);
                    packet_queue_put(&is->videoq, &flush_pkt);
                }
            }

            is->seek_req = 0;
        }

        if(is->audioq.size > MAX_AUDIOQ_SIZE ||
                is->videoq.size > MAX_VIDEOQ_SIZE) {
            SDL_Delay(10);
            continue;
        }

        if(av_read_frame(is->pFormatCtx, packet) < 0) {
            if(is->pFormatCtx->pb->error == 0) {
                SDL_Delay(100); /* no error; wait for user input */
                continue;

            } else {
                break;
            }
        }

        // Is this a packet from the video stream?
        if(packet->stream_index == is->videoStream) {
            packet_queue_put(&is->videoq, packet);

        } else if(packet->stream_index == is->audioStream) {
            packet_queue_put(&is->audioq, packet);

        } else {
            av_free_packet(packet);
        }
    }

    /* all done - wait for it */
    while(!is->quit) {
        SDL_Delay(100);
    }

fail: {
        SDL_Event event;
        event.type = FF_QUIT_EVENT;
        event.user.data1 = is;
        SDL_PushEvent(&event);
    }
    return 0;
}

void stream_seek(VideoState *is, int64_t pos, int rel) {

    if(!is->seek_req) {
        is->seek_pos = pos;
        is->seek_flags = rel < 0 ? AVSEEK_FLAG_BACKWARD : 0;
        is->seek_req = 1;
    }
}

int main(int argc, char *argv[]) {

    SDL_Event       event;
    //double          pts;
    VideoState      *is;

    is = av_mallocz(sizeof(VideoState));

    if(argc < 2) {
        fprintf(stderr, "Usage: test <file>\n");
        exit(1);
    }

    // Register all formats and codecs
    av_register_all();

    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
        exit(1);
    }

    // Make a screen to put our video
#ifndef __DARWIN__
    screen = SDL_SetVideoMode(640, 480, 0, 0);
#else
    screen = SDL_SetVideoMode(640, 480, 24, 0);
#endif

    if(!screen) {
        fprintf(stderr, "SDL: could not set video mode - exiting\n");
        exit(1);
    }

    av_strlcpy(is->filename, argv[1], 1024);

    is->pictq_mutex = SDL_CreateMutex();
    is->pictq_cond = SDL_CreateCond();

    schedule_refresh(is, 40);

    is->av_sync_type = DEFAULT_AV_SYNC_TYPE;
    is->parse_tid = SDL_CreateThread(decode_thread, is);

    if(!is->parse_tid) {
        av_free(is);
        return -1;
    }

    av_init_packet(&flush_pkt);
    flush_pkt.data = (unsigned char *)"FLUSH";

    for(;;) {
        double incr, pos;
        SDL_WaitEvent(&event);

        switch(event.type) {
            case SDL_KEYDOWN:
                switch(event.key.keysym.sym) {
                    case SDLK_LEFT:
                        incr = -10.0;
                        goto do_seek;

                    case SDLK_RIGHT:
                        incr = 10.0;
                        goto do_seek;

                    case SDLK_UP:
                        incr = 60.0;
                        goto do_seek;

                    case SDLK_DOWN:
                        incr = -60.0;
                        goto do_seek;
do_seek:

                        if(global_video_state) {
                            pos = get_master_clock(global_video_state);
                            pos += incr;
                            stream_seek(global_video_state, (int64_t)(pos * AV_TIME_BASE), incr);
                        }

                        break;

                    default:
                        break;
                }

                break;

            case FF_QUIT_EVENT:
            case SDL_QUIT:
                is->quit = 1;
                /*
                 * If the video has finished playing, then both the picture and
                 * audio queues are waiting for more data.  Make them stop
                 * waiting and terminate normally.
                 */
                SDL_CondSignal(is->audioq.cond);
                SDL_CondSignal(is->videoq.cond);
                SDL_Quit();
                exit(0);
                break;

            case FF_ALLOC_EVENT:
                alloc_picture(event.user.data1);
                break;

            case FF_REFRESH_EVENT:
                video_refresh_timer(event.user.data1);
                break;

            default:
                break;
        }
    }

    return 0;
}
Exemple #4
0
int decode_thread(void *arg) {

    VideoState *is = (VideoState *)arg;
    AVFormatContext *pFormatCtx = NULL;
    AVPacket pkt1, *packet = &pkt1;

    AVDictionary *io_dict = NULL;
    AVIOInterruptCB callback;

    int video_index = -1;
    int audio_index = -1;
    int i;

    is->videoStream=-1;
    is->audioStream=-1;

    global_video_state = is;
    // will interrupt blocking functions if we quit!
    callback.callback = decode_interrupt_cb;
    callback.opaque = is;
    if (avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict))
    {
        fprintf(stderr, "Unable to open I/O for %s\n", is->filename);
        return -1;
    }

    // Open video file
    if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL)!=0)
        return -1; // Couldn't open file

    is->pFormatCtx = pFormatCtx;

    // Retrieve stream information
    if(avformat_find_stream_info(pFormatCtx, NULL)<0)
        return -1; // Couldn't find stream information

    // Dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, is->filename, 0);

    // Find the first video stream

    for(i=0; i<pFormatCtx->nb_streams; i++) {
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
                video_index < 0) {
            video_index=i;
        }
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
                audio_index < 0) {
            audio_index=i;
        }
    }
    if(audio_index >= 0) {
        stream_component_open(is, audio_index);
    }
    if(video_index >= 0) {
        stream_component_open(is, video_index);
    }   

    if(is->videoStream < 0 || is->audioStream < 0) {
        fprintf(stderr, "%s: could not open codecs\n", is->filename);
        goto fail;
    }

    // main decode loop
    for(;;) {
        if(is->quit) {
            break;
        }
        // seek stuff goes here
        if(is->audioq.size > MAX_AUDIOQ_SIZE ||
                is->videoq.size > MAX_VIDEOQ_SIZE) {
            SDL_Delay(10);
            continue;
        }
        if(av_read_frame(is->pFormatCtx, packet) < 0) {
            if(is->pFormatCtx->pb->error == 0) {
                SDL_Delay(100); /* no error; wait for user input */
                continue;
            } else {
                break;
            }
        }
        // Is this a packet from the video stream?
        if(packet->stream_index == is->videoStream) {
            packet_queue_put(&is->videoq, packet);
        } else if(packet->stream_index == is->audioStream) {
            packet_queue_put(&is->audioq, packet);
        } else {
            av_free_packet(packet);
        }
    }
    /* all done - wait for it */
    while(!is->quit) {
        SDL_Delay(100);
    }

fail:
    {
        SDL_Event event;
        event.type = FF_QUIT_EVENT;
        event.user.data1 = is;
        SDL_PushEvent(&event);
    }
    return 0;
}
Exemple #5
0
static void *decode_thread(ALLEGRO_THREAD *t, void *arg)
{
   VideoState *is = (VideoState *) arg;
   AVFormatContext *format_context = is->format_context;
   AVPacket pkt1, *packet = &pkt1;

   is->videoStream = -1;
   is->audioStream = -1;

   if (is->audio_index >= 0) {
      stream_component_open(is, is->audio_index);
   }
   if (is->video_index >= 0) {
      stream_component_open(is, is->video_index);
   }

   if (is->videoStream < 0 && is->audioStream < 0) {
      ALLEGRO_ERROR("%s: could not open codecs\n", is->filename);
      goto fail;
   }

   for (;;) {
      if (is->quit) {
         break;
      }

      if (is->seek_req) {
         int stream_index = -1;
         int64_t seek_target = is->seek_pos;

         if (is->videoStream >= 0)
            stream_index = is->videoStream;
         else if (is->audioStream >= 0)
            stream_index = is->audioStream;

         if (stream_index >= 0) {
            seek_target =
                av_rescale_q(seek_target, AV_TIME_BASE_Q,
                             format_context->streams[stream_index]->time_base);
         }
         
         if (av_seek_frame(is->format_context, stream_index, seek_target,
            is->seek_flags) < 0) {
            ALLEGRO_WARN("%s: error while seeking (%d, %lu)\n",
                    is->format_context->filename, stream_index, seek_target);
         }
         else {
            if (is->audioStream >= 0) {
               packet_queue_flush(&is->audioq);
               packet_queue_put(&is->audioq, &flush_pkt);
            }
            if (is->videoStream >= 0) {
               packet_queue_flush(&is->videoq);
               packet_queue_put(&is->videoq, &flush_pkt);
            }
         }
         is->seek_req = 0;
         is->after_seek_sync = true;
         
      }
      if (is->audioq.size > MAX_AUDIOQ_SIZE ||
          is->videoq.size > MAX_VIDEOQ_SIZE) {
         al_rest(0.01);
         continue;
      }
      if (av_read_frame(is->format_context, packet) < 0) {
         #ifdef FFMPEG_0_8
         if (!format_context->pb->eof_reached && !format_context->pb->error) {
         #else
         if (url_ferror((void *)&format_context->pb) == 0) {
         #endif
            al_rest(0.01);
            continue;
         }
         else {
            break;
         }
      }
      // Is this a packet from the video stream?
      if (packet->stream_index == is->videoStream) {
         packet_queue_put(&is->videoq, packet);
      }
      else if (packet->stream_index == is->audioStream) {
         packet_queue_put(&is->audioq, packet);
      }
      else {
         av_free_packet(packet);
      }
   }
   /* all done - wait for it */
   while (!is->quit) {
      al_rest(0.1);
   }

 fail:
   return t;
}

/* We want to be able to send an event to the user exactly at the time
 * a new video frame should be displayed.
 */
static void *timer_thread(ALLEGRO_THREAD *t, void *arg)
{
   VideoState *is = (VideoState *) arg;
   double ot = 0, nt = 0;
   while (!is->quit) {
      ALLEGRO_EVENT event;
      double d;

      /* Wait here until someone signals to us when a new frame was
       * scheduled at is->show_next.
       */
      al_lock_mutex(is->timer_mutex);
      al_wait_cond(is->timer_cond, is->timer_mutex);
      al_unlock_mutex(is->timer_mutex);
      
      if (is->quit) break;
      
      /* Wait until that time. This wait is why we have our own thread
       * here so the user doesn't need to do it.
       */
      while (1) {
         d = is->show_next - get_master_clock(is);
         if (d <= 0) break;
         //printf("waiting %4.1f ms\n", d * 1000);
         al_rest(d);
      }

      nt = get_master_clock(is);
      //printf("event after %4.1f ms\n", (nt - ot) * 1000);
      ot = nt;
      /* Now is the time. */
      event.type = ALLEGRO_EVENT_VIDEO_FRAME_SHOW;
      event.user.data1 = (intptr_t)is->video;
      al_emit_user_event(&is->video->es, &event, NULL);
   }
   return t;
}
int decode_thread(void *arg) {

  VideoState *is = (VideoState *)arg;
  AVFormatContext *pFormatCtx;
  AVPacket pkt1, *packet = &pkt1;

  int video_index = -1;
  int audio_index = -1;
  int i;

  is->videoStream=-1;
  is->audioStream=-1;

  global_video_state = is;
  // will interrupt blocking functions if we quit!
  url_set_interrupt_cb(decode_interrupt_cb);

  // Open video file
  if(av_open_input_file(&pFormatCtx, is->filename, NULL, 0, NULL)!=0)
    return -1; // Couldn't open file

  is->pFormatCtx = pFormatCtx;
  
  // Retrieve stream information
  if(av_find_stream_info(pFormatCtx)<0)
    return -1; // Couldn't find stream information
  
  // Dump information about file onto standard error
  dump_format(pFormatCtx, 0, is->filename, 0);
  
  // Find the first video stream
  for(i=0; i<pFormatCtx->nb_streams; i++) {
    if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO &&
       video_index < 0) {
      video_index=i;
    }
    if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO &&
       audio_index < 0) {
      audio_index=i;
    }
  }
  if(audio_index >= 0) {
    stream_component_open(is, audio_index);
  }
  if(video_index >= 0) {
    stream_component_open(is, video_index);
  }   

  if(is->videoStream < 0 || is->audioStream < 0) {
    fprintf(stderr, "%s: could not open codecs\n", is->filename);
    goto fail;
  }

  // main decode loop

  for(;;) {
    if(is->quit) {
      break;
    }
    // seek stuff goes here
    if(is->seek_req) {
      int stream_index= -1;
      int64_t seek_target = is->seek_pos;

      if     (is->videoStream >= 0) stream_index = is->videoStream;
      else if(is->audioStream >= 0) stream_index = is->audioStream;

      if(stream_index>=0){
	seek_target= av_rescale_q(seek_target, AV_TIME_BASE_Q, pFormatCtx->streams[stream_index]->time_base);
      }
      if(!av_seek_frame(is->pFormatCtx, stream_index, seek_target, is->seek_flags)) {
	fprintf(stderr, "%s: error while seeking\n", is->pFormatCtx->filename);
      } else {
	if(is->audioStream >= 0) {
	  packet_queue_flush(&is->audioq);
	  packet_queue_put(&is->audioq, &flush_pkt);
	}
	if(is->videoStream >= 0) {
	  packet_queue_flush(&is->videoq);
	  packet_queue_put(&is->videoq, &flush_pkt);
	}
      }
      is->seek_req = 0;
    }

    if(is->audioq.size > MAX_AUDIOQ_SIZE ||
       is->videoq.size > MAX_VIDEOQ_SIZE) {
      SDL_Delay(10);
      continue;
    }
    if(av_read_frame(is->pFormatCtx, packet) < 0) {
      if(url_ferror(&pFormatCtx->pb) == 0) {
	SDL_Delay(100); /* no error; wait for user input */
	continue;
      } else {
	break;
      }
    }
    // Is this a packet from the video stream?
    if(packet->stream_index == is->videoStream) {
      packet_queue_put(&is->videoq, packet);
    } else if(packet->stream_index == is->audioStream) {
      packet_queue_put(&is->audioq, packet);
    } else {
      av_free_packet(packet);
    }
  }
  /* all done - wait for it */
  while(!is->quit) {
    SDL_Delay(100);
  }
 fail:
  {
    SDL_Event event;
    event.type = FF_QUIT_EVENT;
    event.user.data1 = is;
    SDL_PushEvent(&event);
  }
  return 0;
}
int decode_thread(void *arg) {

  VideoState *is = (VideoState *)arg;
  AVFormatContext *pFormatCtx = avformat_alloc_context ();
  AVPacket pkt1, *packet = &pkt1;

  int video_index = -1;
  int audio_index = -1;
  int i;

  is->videoStream=-1;
  is->audioStream=-1;
  is->quit = 0;

  Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton ().openResource (is->resourceName);
  if(stream.isNull ())
    throw std::runtime_error("Failed to open video resource");
  is->stream = stream;

  AVIOContext	 *ioContext = 0;

  ioContext = avio_alloc_context(NULL, 0, 0, is, OgreResource_Read, OgreResource_Write, OgreResource_Seek);
  if (!ioContext)
    throw std::runtime_error("Failed to allocate ioContext ");

  pFormatCtx->pb = ioContext;

  global_video_state = is;
  // will interrupt blocking functions if we quit!
  //url_set_interrupt_cb(decode_interrupt_cb);

  // Open video file
  /// \todo leak here, ffmpeg or valgrind bug ?
  if (avformat_open_input(&pFormatCtx, is->resourceName.c_str(), NULL, NULL))
    throw std::runtime_error("Failed to open video input");

  // Retrieve stream information
  if(avformat_find_stream_info(pFormatCtx, NULL)<0)
    throw std::runtime_error("Failed to retrieve stream information");

  // Dump information about file onto standard error
  av_dump_format(pFormatCtx, 0, is->resourceName.c_str(), 0);

  for(i=0; i < (int)pFormatCtx->nb_streams; i++) {
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
       video_index < 0) {
      video_index=i;
    }
    if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
       audio_index < 0) {
      audio_index=i;
    }
  }

  if(audio_index >= 0) {
    stream_component_open(is, audio_index, pFormatCtx);
  }
  if(video_index >= 0) {
    stream_component_open(is, video_index, pFormatCtx);
  }

  if(is->videoStream >= 0 /*|| is->audioStream < 0*/)
  {

    // main decode loop

    for(;;) {
      if(is->quit) {
        break;
      }
      if( (is->audioStream >= 0 && is->audioq.size > MAX_AUDIOQ_SIZE) ||
         is->videoq.size > MAX_VIDEOQ_SIZE) {
        boost::this_thread::sleep(boost::posix_time::milliseconds(10));
        continue;
      }
      if(av_read_frame(pFormatCtx, packet) < 0) {
        break;
      }
      // Is this a packet from the video stream?
      if(packet->stream_index == is->videoStream) {
        packet_queue_put(&is->videoq, packet);
      } else if(packet->stream_index == is->audioStream) {
        packet_queue_put(&is->audioq, packet);
      } else {
        av_free_packet(packet);
      }
    }
    /* all done - wait for it */
    while(!is->quit) {
      // EOF reached, all packets processed, we can exit now
      if (is->audioq.nb_packets == 0 && is->videoq.nb_packets == 0)
        break;
      boost::this_thread::sleep(boost::posix_time::milliseconds(100));
    }
  }

  is->quit = 1;

  is->audioq.cond.notify_one();
  is->videoq.cond.notify_one();
 
  if (is->video_thread.joinable())
	is->video_thread.join();

  if (is->audioStream >= 0)
    avcodec_close(is->audio_st->codec);
  if (is->videoStream >= 0)
    avcodec_close(is->video_st->codec);

  sws_freeContext (is->sws_context);
  avformat_close_input(&pFormatCtx);
  pFormatCtx = NULL;

  av_free(ioContext);

  return 0;
}
Exemple #8
0
void *decode_thread(void *arg)
{
    //fprintf(stdout, "[FFmpeg-main thread] decode_thread created\n");
    VideoState *is = (VideoState *)arg;
    AVFormatContext *pFormatCtx = NULL;
    AVPacket pkt1, *packet = &pkt1;
    
    AVIOInterruptCB callback;
    
    int video_index = -1;
    int i;
    
    is->videoStream=-1;
    
    // Will interrupt blocking functions ifwe quit!
    callback.callback = decode_interrupt_cb;
    callback.opaque = is;
    
    fprintf(stdout, "[FFmpeg-decode thread] Try to open I/O\n");
    if(avio_open2(&is->io_context, is->filename, 0, &callback, NULL) < 0)
    {
        fprintf(stdout, "Unable to open I/O for file\n");
        return NULL;
    }
    //fprintf(stdout, "avio_open2 done\n");
    
    // Open video file
    fprintf(stdout, "[FFmpeg-decode thread] Try to open format context\n");
    if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL)!=0)
    {
        fprintf(stdout, "Couldn't Open file\n");
        return NULL; // Couldn't open file
    }
    //fprintf(stdout, "open_input done\n");
    
    is->pFormatCtx = pFormatCtx;
    
    // Retrieve stream information
    fprintf(stdout, "[FFmpeg-decode thread] Try to Retrieve stream info\n");
    if(avformat_find_stream_info(pFormatCtx, NULL)<0)
    {
        fprintf(stdout, "Couldn't Retrieve stream information\n");
        return NULL; // Couldn't find stream information
    }
    
    // Dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, is->filename, 0);
    
    // Find the first video stream
    for(i=0; i<pFormatCtx->nb_streams; i++)
    {
        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
           video_index < 0)
        {
            video_index=i;
            break;
        }
    }
    if(video_index == -1)
    {
        fprintf(stdout, "Couldn't find video stream\n");
        return NULL;
    }
    //fprintf(stdout, "stream component open\n");
    stream_component_open(is, video_index);
    
    // main decode loop
    //fprintf(stdout, "[FFmpeg-decode thread] read frame\n");
    for(;;)
    {
        if(is->quit)
        {
            break;
        }
        if(av_read_frame(is->pFormatCtx, packet) < 0)
        {
            if(is->pFormatCtx->pb->error == 0)
                continue;
            else
                break;
        }
        if(packet->stream_index == is->videoStream)
        {
            packet_queue_put(&is->videoq, packet);
            //fprintf(stdout, "packs ready to load: %d\n",is->videoq.nb_packets);
        }
        else
            av_free_packet(packet);
    }
    fprintf(stdout, "[FFmpeg-decode thread] thread terminated\n");
    return NULL;
}
int decode_thread(void *arg){

	VideoState *is = (VideoState *) arg;
	AVFormatContext *pFormatCtx = NULL;
	AVPacket pkt1, *packet = &pkt1;
	int video_index = -1;
	int audio_index = -1;
	int i;
	is->videoStream = -1;
	is->audioStream = -1;
	AVDictionary *io_dic = NULL;
	AVIOInterruptCB interupt_cb;
	//global_video_state = is;

	
	interupt_cb.callback = decode_interrupt_cb;		// will interrupt blocking functions if we quit!
	interupt_cb.opaque = is;
	if (avio_open2(&is->io_ctx, is->filename, 0, &interupt_cb, &io_dic)){
		fprintf(stderr, "Cannot open I/O for %s\n", is->filename);
		return -1;
	}
	// Open video file
	if (avformat_open_input(&pFormatCtx, is->filename, NULL, NULL) != 0){
		return -1; // Couldn't open file
	}
	is->pFormatCtx = pFormatCtx;
	// Retrieve stream information
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0){
		return -1; 		// Couldn't find stream information
	}	
	av_dump_format(pFormatCtx, 0, is->filename, 0);		// Dump information about file onto standard error

	// Find the first video stream
	for (i = 0; i < pFormatCtx->nb_streams; i++){
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0){
			video_index = i;
		}
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0){
			audio_index = i;
		}
	}
	if (audio_index >= 0){
		stream_component_open(is, audio_index);
	}
	if (video_index >= 0){
		stream_component_open(is, video_index);
	}
	if (is->videoStream < 0 || is->audioStream < 0){
		fprintf(stderr, "%s: could not open codecs\n", is->filename);
		goto fail;
	}

	// main decode loop
	for (;;) {
		if (is->quit){
		break;
	}
	// seek stuff goes here
	if(is->seek_req){
		int str_index = -1;
		int64_t seek_trgt = is->seek_pos;
		if (is->videoStream >= 0 ){
			str_index = is->videoStream;
		}else if (is->audioStream >= 0){
			str_index = is->audioStream;
		}
		if (str_index >= 0){
			seek_trgt = av_rescale_q(seek_trgt, AV_TIME_BASE_Q, pFormatCtx->streams[str_index]->time_base);
		}
		if(av_seek_frame(is->pFormatCtx, str_index, seek_trgt, is->seek_flag) < 0 ){
			fprintf(stderr , "%s : seeking error\n", is->pFormatCtx->filename);
		}else{
			if (is->audioStream >= 0){
				packet_queue_f(&is->audioq);
				packet_queue_put(&is->audioq,&f_pkt);
			}
			if (is->videoStream >= 0){
				packet_queue_f(&is->videoq);
				packet_queue_put(&is->videoq,&f_pkt);
			}
		}
		is->seek_req = 0 ;
	}
	/*if (is->audioq.size > MAX_AUDIOQ_SIZE || is->videoq.size > MAX_VIDEOQ_SIZE){
		SDL_Delay(10);
		continue;
	}		// !!!! maybe need to remove this func !!! ^^^*/
	if (av_read_frame(is->pFormatCtx, packet) < 0){
	    if (is->pFormatCtx->pb->error == 0) {
			SDL_Delay(100); /* no error; wait for user input */
		  	continue;
		} else {
			break;
		}
	}
	// Is this a packet from the video stream?
	if (packet->stream_index == is->videoStream){
		packet_queue_put(&is->videoq, packet);
	} else if (packet->stream_index == is->audioStream){
		packet_queue_put(&is->audioq, packet);
	} else {
		av_free_packet(packet);
		}
	}
	/* all done - wait for it */
	while (!is->quit) {
		SDL_Delay(100);
	}

	fail:{
		SDL_Event event;
		event.type = FF_QUIT_EVENT;
		event.user.data1 = is;
		SDL_PushEvent(&event);
	}
	return 0;
}
int player_prepare(State **ps, int from_thread)
{
	int audio_index = -1;
	int video_index = -1;
	int i;

	State *state = *ps;
	
	if (state && state->pFormatCtx) {
		avformat_close_input(&state->pFormatCtx);
	}

	state->pFormatCtx = NULL;
	state->audio_stream = -1;
	state->video_stream = -1;
	state->audio_st = NULL;
	state->video_st = NULL;

    printf("Path: %s\n", state->filename);

    AVDictionary *options = NULL;
    av_dict_set(&options, "user-agent", "FFmpegMediaPlayer", 0);
    
    if (avformat_open_input(&state->pFormatCtx, state->filename, NULL, &options) != 0) {
	    printf("Input file could not be opened\n");
		*ps = NULL;
    	return FAILURE;
    }

	if (avformat_find_stream_info(state->pFormatCtx, NULL) < 0) {
	    printf("Stream information could not be retrieved\n");
	    avformat_close_input(&state->pFormatCtx);
		*ps = NULL;
    	return FAILURE;
	}

	char duration[30] = "0";
	get_duration(state->pFormatCtx, duration);
	av_dict_set(&state->pFormatCtx->metadata, DURATION, duration, 0);
	
    // Find the first audio and video stream
	for (i = 0; i < state->pFormatCtx->nb_streams; i++) {
		if (state->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0) {
			video_index = i;
		}

		if (state->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0) {
			audio_index = i;
		}
		
		set_codec(state->pFormatCtx, i);
	}

	if (audio_index >= 0) {
		stream_component_open(state, audio_index, from_thread);
	}

	if (video_index >= 0) {
		stream_component_open(state, video_index, from_thread);
	}

	if (state->video_stream < 0 && state->audio_stream < 0) {
	    avformat_close_input(&state->pFormatCtx);
		*ps = NULL;
		return FAILURE;
	}

	state->pFormatCtx->interrupt_callback.callback = decode_interrupt_cb;
	state->pFormatCtx->interrupt_callback.opaque = state;
	
    // fill the inital buffer
	AVPacket packet;
	memset(&packet, 0, sizeof(packet)); //make sure we can safely free it

	int j, ret;
    int bytes_written = 0;
	
	while (bytes_written < state->buffer_size) {
		for (j = 0; j < state->pFormatCtx->nb_streams; j++) {
			//av_init_packet(&packet);
			ret = av_read_frame(state->pFormatCtx, &packet);

			if (ret < 0) {
				if (ret == AVERROR_EOF || url_feof(state->pFormatCtx->pb)) {
					//break;
			    }
			}

			int frame_size_ptr = 0;
			ret = decode_frame_from_packet(state, &packet, &frame_size_ptr, from_thread);
		    __android_log_print(ANDROID_LOG_ERROR, "TAG", "Fill buffer: %d -> %d", frame_size_ptr, state->buffer_size);
			bytes_written = bytes_written + frame_size_ptr;
			av_free_packet(&packet);
		}
	}
		
	*ps = state;

	state->notify_callback(state->clazz, MEDIA_PREPARED, 0, 0, from_thread);

	return SUCCESS;
}
Exemple #11
0
int decode_thread(void *arg) {

    VideoState *is = (VideoState *)arg;
    AVFormatContext *pFormatCtx = NULL;
    AVPacket pkt1, *packet = &pkt1;

    AVDictionary *io_dict = NULL;
    AVIOInterruptCB callback;

    int video_index = -1;
    int audio_index = -1;
    int i;

    is->videoStream = -1;
    is->audioStream = -1;
    is->audio_need_resample = 0;

    global_video_state = is;
    // will interrupt blocking functions if we quit!
    callback.callback = decode_interrupt_cb;
    callback.opaque = is;

    if(avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict)) {
        fprintf(stderr, "Unable to open I/O for %s\n", is->filename);
        return -1;
    }

    // Open video file
    if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL) != 0) {
        return -1;    // Couldn't open file
    }

    is->pFormatCtx = pFormatCtx;

    // Retrieve stream information
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        return -1;    // Couldn't find stream information
    }

    // Dump information about file onto standard error
    av_dump_format(pFormatCtx, 0, is->filename, 0);

    // Find the first video stream

    for(i = 0; i < pFormatCtx->nb_streams; i++) {
        if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
                video_index < 0) {
            video_index = i;
        }

        if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO &&
                audio_index < 0) {
            audio_index = i;
        }
    }

    if(audio_index >= 0) {
        stream_component_open(is, audio_index);
    }

    if(video_index >= 0) {
        stream_component_open(is, video_index);
    }

    if(is->videoStream < 0 && is->audioStream < 0) {
        fprintf(stderr, "%s: could not open codecs\n", is->filename);
        goto fail;
    }

#ifdef __RESAMPLER__

    if( audio_index >= 0
            && pFormatCtx->streams[audio_index]->codec->sample_fmt != AV_SAMPLE_FMT_S16) {
        is->audio_need_resample = 1;
        is->pResampledOut = NULL;
        is->pSwrCtx = NULL;

        printf("Configure resampler: ");

#ifdef __LIBAVRESAMPLE__
        printf("libAvResample\n");
        is->pSwrCtx = avresample_alloc_context();
#endif

#ifdef __LIBSWRESAMPLE__
        printf("libSwResample\n");
        is->pSwrCtx = swr_alloc();
#endif

        // Some MP3/WAV don't tell this so make assumtion that
        // They are stereo not 5.1
        if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0
                && pFormatCtx->streams[audio_index]->codec->channels == 2) {
            pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO;

        } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0
                   && pFormatCtx->streams[audio_index]->codec->channels == 1) {
            pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_MONO;

        } else if (pFormatCtx->streams[audio_index]->codec->channel_layout == 0
                   && pFormatCtx->streams[audio_index]->codec->channels == 0) {
            pFormatCtx->streams[audio_index]->codec->channel_layout = AV_CH_LAYOUT_STEREO;
            pFormatCtx->streams[audio_index]->codec->channels = 2;
        }

        av_opt_set_int(is->pSwrCtx, "in_channel_layout",
                       pFormatCtx->streams[audio_index]->codec->channel_layout, 0);
        av_opt_set_int(is->pSwrCtx, "in_sample_fmt",
                       pFormatCtx->streams[audio_index]->codec->sample_fmt, 0);
        av_opt_set_int(is->pSwrCtx, "in_sample_rate",
                       pFormatCtx->streams[audio_index]->codec->sample_rate, 0);

        av_opt_set_int(is->pSwrCtx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
        av_opt_set_int(is->pSwrCtx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
        av_opt_set_int(is->pSwrCtx, "out_sample_rate", 44100, 0);

#ifdef __LIBAVRESAMPLE__

        if (avresample_open(is->pSwrCtx) < 0) {
#else

        if (swr_init(is->pSwrCtx) < 0) {
#endif
            fprintf(stderr, " ERROR!! From Samplert: %d Hz Sample format: %s\n",
                    pFormatCtx->streams[audio_index]->codec->sample_rate,
                    av_get_sample_fmt_name(pFormatCtx->streams[audio_index]->codec->sample_fmt));
            fprintf(stderr, "         To 44100 Sample format: s16\n");
            is->audio_need_resample = 0;
            is->pSwrCtx = NULL;;
        }

    }

#endif

    // main decode loop

    for(;;) {
        if(is->quit) {
            break;
        }

        // seek stuff goes here
        if(is->audioq.size > MAX_AUDIOQ_SIZE ||
                is->videoq.size > MAX_VIDEOQ_SIZE) {
            SDL_Delay(10);
            continue;
        }

        if(av_read_frame(is->pFormatCtx, packet) < 0) {
            if(is->pFormatCtx->pb->error == 0) {
                SDL_Delay(100); /* no error; wait for user input */
                continue;

            } else {
                break;
            }
        }

        // Is this a packet from the video stream?
        if(packet->stream_index == is->videoStream) {
            packet_queue_put(&is->videoq, packet);

        } else if(packet->stream_index == is->audioStream) {
            packet_queue_put(&is->audioq, packet);

        } else {
            av_free_packet(packet);
        }
    }

    /* all done - wait for it */
    while(!is->quit) {
        SDL_Delay(100);
    }

fail: {
        SDL_Event event;
        event.type = FF_QUIT_EVENT;
        event.user.data1 = is;
        SDL_PushEvent(&event);
    }
    return 0;
}

const char g_szClassName[] = "myWindowClass";

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

sem_t mutex;
HWND hwnd;

static void * window_manager(void * data) {
    printf("Window manager has been started!\n");
    WNDCLASSEX wc;

    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    //wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               g_szClassName,
               "The title of my window",
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, NULL, NULL);
    sem_post(&mutex);
    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    } else {
        printf("window hwnd = %d\n", hwnd);
    }

    ShowWindow(hwnd, TRUE);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}
Exemple #12
0
int decode_thread(void* arg) {
//	CoInitialize(NULL);
	CoInitializeEx(NULL, COINIT_MULTITHREADED);
	printf("decode_thread\n");
	VideoState* is = (VideoState*) arg;
	AVFormatContext* pFormatCtx;
	AVPacket pkt1, *packet = &pkt1;

	int video_index = -1;
	int audio_index = -1;
	int i;

	global_video_state = is;

	if (avformat_open_input(&pFormatCtx, is->filename, NULL, NULL) != 0) {
		return -1;
	}

	is->pFormatCtx = pFormatCtx;
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
		return -1;
	}

	av_dump_format(pFormatCtx, 0, is->filename, 0);

	for (i = 0; i < pFormatCtx->nb_streams; i++) {
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO
				&& video_index < 0)
			video_index = i;
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO
				&& audio_index < 0)
			audio_index = i;
	}

	if (audio_index >= 0)
		stream_component_open(is, audio_index);

	if (video_index >= 0)
		stream_component_open(is, video_index);

	if (is->videoStream < 0 || is->audioStream < 0) {
		fprintf(stderr, "%s: could not open codecs\n", is->filename);
		goto fail;
	}

// main decode loop
	for (;;) {
		if (is->quit) {
			SDL_LockMutex(is->audioq.mutex);
			SDL_CondSignal(is->audioq.cond);
			SDL_UnlockMutex(is->audioq.mutex);
			break;
		}

		//seek stuff goes here
		if (is->seek_req) {
			int stream_index = -1;
			int64_t seek_target = is->seek_pos;
			if (is->videoStream >= 0)
				stream_index = is->videoStream;
			else if (is->audioStream >= 0)
				stream_index = is->audioStream;

			if (stream_index >= 0) {
				seek_target = av_rescale_q(seek_target, AV_TIME_BASE_Q,
						pFormatCtx->streams[stream_index]->time_base);
			}

			if (av_seek_frame(is->pFormatCtx, stream_index, seek_target,
					is->seek_flags) < 0) {
				fprintf(stderr, "%s: error while seeking\n",
						is->pFormatCtx->filename);
			} else {
				if (is->audioStream >= 0) {
					packet_queue_flush(&is->audioq);
					packet_queue_put(&is->audioq, &flush_pkt, 0);
				}
			}
			is->seek_req = 0;
		}

		if (is->audioq.size > MAX_AUDIOQ_SIZE
				|| is->videoq.size > MAX_AUDIOQ_SIZE) {
			SDL_Delay(10);
			continue;
		}
		if (av_read_frame(is->pFormatCtx, packet) < 0) {
			printf("av_read_frame\n");
			fflush(stdout);
			if (is->pFormatCtx->pb->error == 0) {
				SDL_Delay(100); // no error, wait for user input
				continue;
			} else {
				break;
			}
		}

		if (packet->stream_index == is->videoStream) {
			packet_queue_put(&is->videoq, packet, 1);
		} else if (packet->stream_index == is->audioStream) {
			packet_queue_put(&is->audioq, packet, 0);
		} else {
			av_free_packet(packet);
		}
	}

// all done - wait for it
	while (!is->quit) {
		SDL_Delay(100);
	}

	fail: if (1) {
		SDL_Event event;
		event.type = FF_QUIT_EVENT;
		event.user.data1 = is;
		SDL_PushEvent(&event);
	}
	return 0;
}
Exemple #13
0
int decode_thread( void *thread_arg )
{
  VideoState *is = (VideoState *) thread_arg;
  AVFormatContext *pFormatCtx;
  AVPacket pkt1, *packet = &pkt1;
  //global_video_state = is;
  url_set_interrupt_cb(decode_interrupt_cb); // will interrupt blocking functions if we quit!

//  is->filename[0] = *"./foo.mkv";
  strcpy(is->filename, "./foo.mkv");

  int i;
  //AVCodecContext *pCodecCtx;
  //AVCodecContext *aCodecCtx;

  // Open video file
  if( av_open_input_file(&pFormatCtx, is->filename, NULL, 0, NULL) != 0 )
    return -1; // Couldn't open file
  is->pFormatCtx = pFormatCtx;

  // Retrieve stream information
  if(av_find_stream_info(pFormatCtx)<0)
    return -1; // Couldn't find stream information

  // Dump information about file onto standard error
  //dump_format(pFormatCtx, 0, is->filename, 0);

  // Find the video stream and audio stream
  int videoStream = -1;
  int audioStream = -1;
  is->videoStream = -1;
  is->audioStream = -1;
  for( i=0; i<pFormatCtx->nb_streams; i++ )
  {
    if( pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) {
      videoStream = i;
    }
    if( pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO && audioStream < 0 ) {
      audioStream = i;
    }
  }

  if(videoStream == -1)
    return -1; // Didn't find a video stream
  if(audioStream == -1)
    printf( "No audio stream\n" );
  else
    stream_component_open( is, audioStream );

  stream_component_open( is, videoStream );

  if(is->videoStream < 0 ) {
    fprintf(stderr, "%s: could not open codecs\n", is->filename);
    goto fail;
  } 

  // Decode loop
  for(;;) {
    if(is->quit) {
      break;
    }
    if(is->audioq.size > MAX_AUDIOQ_SIZE ||
       is->videoq.size > MAX_VIDEOQ_SIZE) {
      SDL_Delay(10);
      continue;
    }
/*
    if( av_read_frame(is->pFormatCtx, packet) < 0 ) {
      if( url_ferror((ByteIOContext *)&pFormatCtx->pb) == 0 ) {
        SDL_Delay(100); // no error; wait for user input
        continue;
      } else {
        break;
      }
    }

    // Queue the packets into the right queue
    if(packet->stream_index == is->videoStream) {
      packet_queue_put(&is->videoq, packet);
    } else if(packet->stream_index == is->audioStream) {
      packet_queue_put(&is->audioq, packet);
    } else {
      av_free_packet(packet);
    }
*/
  }

  while(!is->quit) {
    SDL_Delay(100);
  }

 fail:
  if(1){
    SDL_Event event;
    event.type = FF_QUIT_EVENT;
    event.user.data1 = is;
    SDL_PushEvent(&event);
  }
  return 0;

} // End decode_thread()
Exemple #14
0
static int decode_thread(void *arg) {
    VideoState *is = (VideoState *)arg;
    AVFormatContext *ic = NULL;
    AVPacket pkt1, *packet = &pkt1;
    int ret, i;
	int video_index = -1;

	is->videoStream = -1;

    global_video_state = is;
    if (avformat_open_input(&ic, is->filename, NULL, NULL) != 0) {
        return -1;
    }

    /* 这个回调函数将赋值给AVFormatContex,这样当读取流出现问题的时候会调用我们的自己的处理 */
	static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
	ic->interrupt_callback = int_cb;

    is->ic = ic;
	is->external_clock_base = 0;
	is->external_clock_base = get_external_clock(is);

    if (avformat_find_stream_info(ic, NULL) < 0) {
        return -1;
    }

    av_dump_format(ic, 0, is->filename, 0);

    for(i=0; i<ic->nb_streams; i++) {
		if(ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0)
			video_index = i;
    }
	
	if(video_index >= 0) stream_component_open(is, video_index); 

    /* 开始解码主循环 */
    for(;;) {
        if(is->quit) 
		  break;
		/* 这里处理视频的快进和快退 */
		if(is->seek_req) {
			int stream_index = -1;
			int64_t seek_target = is->seek_pos;

			is->external_clock_base = 0;
			is->external_clock_base = get_external_clock(is) - (seek_target / 1000000.0);
			
			if(is->videoStream >= 0) 
			  stream_index = is->videoStream;
		
			/* av_rescale_q(a, b, c):通过计算a*b/c来把一个时间基调整到另一个时间基 */
			/* 使用这个函数的原因是可以防止计算溢出,AV_TIME_BASE_Q是AV_TIME_BASE作*/
			/* 为分母的版本                                                        */
			if(stream_index >= 0) 
				seek_target = av_rescale_q(seek_target, AV_TIME_BASE_Q , ic->streams[stream_index]->time_base);

			if(av_seek_frame(is->ic, stream_index, seek_target, is->seek_flags) < 0) {
				fprintf(stderr, "%d: %s error seek\n", __LINE__, is->filename);
			} else {
				/* 跳转后需要清空我们自己的缓冲队列和avcodec内部缓冲*/
				/* 然后放入一个用来标识刷新队列的标志包             */
				if(is->videoStream >= 0) {
					packet_queue_flush(&is->videoq);
					packet_queue_put(&is->videoq, &flush_pkt);
				}
			}

			is->seek_req = 0;
		}
		//printf("decode_thread loop check videoq size %d\n", is->videoq.size);
        if (is->videoq.size > MAX_VIDEOQ_SIZE) {
			//printf("decode_thread loop delay %d\n", is->videoq.size);
            SDLMOD_Delay(10);
            continue;
        }

        ret = av_read_frame(is->ic, packet);
        if (ret < 0) {
            if(ret == AVERROR_EOF || url_feof(is->ic->pb)) {
                break;
            }
            if(is->ic->pb && is->ic->pb->error) {
                break;
            }
            continue;
        }

		if(packet->stream_index == is->videoStream) {
			packet_queue_put(&is->videoq, packet);
        } else {
            av_free_packet(packet);
        }
        //printf("decode_thread loop %d\n", is->videoq.size);
    }

	printf("decode_thread loop wait start\n");
	save_bmp();
    while (!is->quit && is->videoq.size > 0) {
        //printf("decode_thread delay %d\n", is->videoq.size);
        SDLMOD_Delay(100);
    }

fail: {
        SDLMOD_Event event;
        event.type = FF_QUIT_EVENT;
        event.user.data1 = is;
        SDLMOD_PushEvent(&event);
        printf("push FF_QUIT_EVENT\n");
    }

    return 0;
}
int set_data_source_l(State **ps, const char* path) {
    printf("set_data_source\n");
    int audio_index = -1;
    int video_index = -1;
    int i;
    
    State *state = *ps;
    
    printf("Path: %s\n", path);
    
    AVDictionary *options = NULL;
    av_dict_set(&options, "icy", "1", 0);
    av_dict_set(&options, "user-agent", "FFmpegMediaMetadataRetriever", 0);
    
    if (state->headers) {
        av_dict_set(&options, "headers", state->headers, 0);
    }
    
    if (state->offset > 0) {
        state->pFormatCtx = avformat_alloc_context();
        state->pFormatCtx->skip_initial_bytes = state->offset;
    }
    
    if (avformat_open_input(&state->pFormatCtx, path, NULL, &options) != 0) {
        printf("Metadata could not be retrieved\n");
        *ps = NULL;
        return FAILURE;
    }
    
    if (avformat_find_stream_info(state->pFormatCtx, NULL) < 0) {
        printf("Metadata could not be retrieved\n");
        avformat_close_input(&state->pFormatCtx);
        *ps = NULL;
        return FAILURE;
    }
    
    set_duration(state->pFormatCtx);
    
    set_shoutcast_metadata(state->pFormatCtx);
    
    //av_dump_format(state->pFormatCtx, 0, path, 0);
    
    // Find the first audio and video stream
    for (i = 0; i < state->pFormatCtx->nb_streams; i++) {
        if (state->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0) {
            video_index = i;
        }
        
        if (state->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0) {
            audio_index = i;
        }
        
        set_codec(state->pFormatCtx, i);
    }
    
    if (audio_index >= 0) {
        stream_component_open(state, audio_index);
    }
    
    if (video_index >= 0) {
        stream_component_open(state, video_index);
    }
    
    /*if(state->video_stream < 0 || state->audio_stream < 0) {
	    avformat_close_input(&state->pFormatCtx);
     *ps = NULL;
     return FAILURE;
     }*/
    
    set_rotation(state->pFormatCtx, state->audio_st, state->video_st);
    set_framerate(state->pFormatCtx, state->audio_st, state->video_st);
    set_filesize(state->pFormatCtx);
    set_chapter_count(state->pFormatCtx);
    
    /*printf("Found metadata\n");
     AVDictionaryEntry *tag = NULL;
     while ((tag = av_dict_get(state->pFormatCtx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
    	printf("Key %s: \n", tag->key);
    	printf("Value %s: \n", tag->value);
     }*/
    
    *ps = state;
    return SUCCESS;
}
int decode_thread(void *arg) {

  VideoState *is = (VideoState *)arg;
  AVPacket pkt1, *packet = &pkt1;

  AVDictionary *io_dict = NULL;
  AVIOInterruptCB callback;

  int video_index = -1;
  int audio_index = -1;
  int i;

  int ret;
  int eof = 0;

  is->videoStream=-1;
  is->audioStream=-1;

  AVDictionary *options = NULL;
  av_dict_set(&options, "icy", "1", 0);
  av_dict_set(&options, "user-agent", "FFmpegMediaPlayer", 0);
    
  if (is->headers) {
    av_dict_set(&options, "headers", is->headers, 0);
  }

  if (is->offset > 0) {
    is->pFormatCtx = avformat_alloc_context();
    is->pFormatCtx->skip_initial_bytes = is->offset;
    //is->pFormatCtx->iformat = av_find_input_format("mp3");
  }

  // will interrupt blocking functions if we quit!
  callback.callback = decode_interrupt_cb;
  callback.opaque = is;
  if (avio_open2(&is->io_context, is->filename, 0, &callback, &io_dict))
  {
    fprintf(stderr, "Unable to open I/O for %s\n", is->filename);
    return -1;
  }

  // Open video file
  if(avformat_open_input(&is->pFormatCtx, is->filename, NULL, &options)!=0)
    return -1; // Couldn't open file

  // Retrieve stream information
  if(avformat_find_stream_info(is->pFormatCtx, NULL)<0)
    return -1; // Couldn't find stream information

  // Dump information about file onto standard error
  av_dump_format(is->pFormatCtx, 0, is->filename, 0);

  // Find the first video stream
  for(i=0; i<is->pFormatCtx->nb_streams; i++) {
    if(is->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
       video_index < 0) {
      video_index=i;
    }
    if(is->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
       audio_index < 0) {
      audio_index=i;
    }
      
    set_codec(is->pFormatCtx, i);
  }
  if(audio_index >= 0) {
    stream_component_open(is, audio_index);
  }
  if(video_index >= 0) {
    stream_component_open(is, video_index);
  }

  if(is->videoStream < 0 && is->audioStream < 0) {
  //if(is->videoStream < 0 || is->audioStream < 0) {
    fprintf(stderr, "%s: could not open codecs\n", is->filename);
    notify(is, MEDIA_ERROR, 0, 0);
    return 0;
  }

  set_rotation(is->pFormatCtx, is->audio_st, is->video_st);
  set_framerate(is->pFormatCtx, is->audio_st, is->video_st);
  set_filesize(is->pFormatCtx);
  set_chapter_count(is->pFormatCtx);

  // main decode loop

  for(;;) {
    if(is->quit) {
      break;
    }

    /*if (is->paused != is->last_paused) {
        is->last_paused = is->paused;
        if (is->paused)
            is->read_pause_return = av_read_pause(is->pFormatCtx);
        else
            av_read_play(is->pFormatCtx);
    }*/

    // seek stuff goes here
    if(is->seek_req) {
		int64_t seek_target = is->seek_pos;
		int64_t seek_min    = is->seek_rel > 0 ? seek_target - is->seek_rel + 2: INT64_MIN;
		int64_t seek_max    = is->seek_rel < 0 ? seek_target - is->seek_rel - 2: INT64_MAX;

		int ret = avformat_seek_file(is->pFormatCtx, -1, seek_min, seek_target, seek_max, is->seek_flags);
      if(ret < 0) {
	fprintf(stderr, "%s: error while seeking\n", is->pFormatCtx->filename);
      } else {
	if(is->audioStream >= 0) {
	  packet_queue_flush(&is->audioq);
	  packet_queue_put(is, &is->audioq, &is->flush_pkt);
	}
	if(is->videoStream >= 0) {
	  packet_queue_flush(&is->videoq);
	  packet_queue_put(is, &is->videoq, &is->flush_pkt);
	}
	notify(is, MEDIA_SEEK_COMPLETE, 0, 0);

      }
      is->seek_req = 0;
      eof = 0;
    }

    if (is->audioq.size >= MAX_AUDIOQ_SIZE && !is->prepared) {
        queueAudioSamples(&is->audio_player, is);

		notify(is, MEDIA_PREPARED, 0, 0);
    	is->prepared = 1;
    }

    if(is->audioq.size > MAX_AUDIOQ_SIZE ||
       is->videoq.size > MAX_VIDEOQ_SIZE) {
      SDL_Delay(10);
      continue;
    }
    if((ret = av_read_frame(is->pFormatCtx, packet)) < 0) {
      if (ret == AVERROR_EOF || !is->pFormatCtx->pb->eof_reached) {
          eof = 1;
    	  break;
      }

      if(is->pFormatCtx->pb->error == 0) {
	SDL_Delay(100); /* no error; wait for user input */
	continue;
      } else {
	break;
      }
    }
    // Is this a packet from the video stream?
    if(packet->stream_index == is->videoStream) {
      packet_queue_put(is, &is->videoq, packet);
    } else if(packet->stream_index == is->audioStream) {
      packet_queue_put(is, &is->audioq, packet);
    } else {
      av_free_packet(packet);
    }

	if (eof) {
		break;
	}
  }

  if (eof) {
      notify(is, MEDIA_PLAYBACK_COMPLETE, 0, 0);
  }
  return 0;
}
Exemple #17
0
static int read_thread(void *arg)
{
	VideoState *is = (VideoState*)arg;
	AVFormatContext *ic = NULL;
	int i;
	int st_index[AVMEDIA_TYPE_NB]; // 讲解一下
	AVPacket pkt1, *pkt = &pkt1;

	memset(st_index, -1, sizeof(st_index));

	ic = avformat_alloc_context();
	avformat_open_input(&ic, is->filename, NULL, NULL);
	is->ic = ic;

	avformat_find_stream_info(ic, NULL);
	
	for (i = 0; i<ic->nb_streams; i++) 
	{
		if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
			st_index[AVMEDIA_TYPE_VIDEO] = i;
		if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
			st_index[AVMEDIA_TYPE_AUDIO] = i;
	}

	/* open the streams,并开启相应的解码线程 */
	if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
		stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
	}

	if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
		stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
	}

	if (is->video_stream < 0 && is->audio_stream < 0) {
		av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n",
			is->filename);
		goto fail;
	}

	for (;;) {

		/* if the queue are full, no need to read more */
		// 暂时把以下这个判断注掉,不限制packet queue的大小
		// 不然的话,可能因为视频消耗packet比较慢(比如我们强制41ms刷新一次),导致视频queue超过max
		// 此时如果不再读包,会导致音频没包可解,听起来就是杂音
		/*
		if (is->audioq.size > MAX_AUDIOQ_SIZE ||
		is->videoq.size > MAX_VIDEOQ_SIZE) {
		SDL_Delay(10);
		continue;
		}
		*/
		if (av_read_frame(ic, pkt) < 0) {
			//break;
		}
		if (pkt->stream_index == is->audio_stream) {
			packet_queue_put(&is->audioq, pkt);
		}
		else if (pkt->stream_index == is->video_stream) {
			packet_queue_put(&is->videoq, pkt);
		}
		else {
			av_free_packet(pkt);
		}
	}
fail:
	/* close each stream */
	// TODO close streams
	if (ic) {
		avformat_close_input(&ic);
		is->ic = NULL;
	}
	SDL_Event event;
	event.type = FF_QUIT_EVENT;
	event.user.data1 = is;
	SDL_PushEvent(&event);
	return 0;
}
int set_data_source(State **ps, const char* path) {
	printf("set_data_source\n");
	int audio_index = -1;
	int video_index = -1;
	int i;

	State *state = *ps;
	
	if (state && state->pFormatCtx) {
		avformat_close_input(&state->pFormatCtx);
	}

	if (!state) {
		state = av_mallocz(sizeof(State));
	}

	state->pFormatCtx = NULL;
	state->audio_stream = -1;
	state->video_stream = -1;
	state->audio_st = NULL;
	state->video_st = NULL;
	
	char duration[30] = "0";

    printf("Path: %s\n", path);

    AVDictionary *options = NULL;
    av_dict_set(&options, "icy", "1", 0);
    av_dict_set(&options, "user-agent", "FFmpegMediaMetadataRetriever", 0);
    
    if (avformat_open_input(&state->pFormatCtx, path, NULL, &options) != 0) {
	    printf("Metadata could not be retrieved\n");
		*ps = NULL;
    	return FAILURE;
    }

	if (avformat_find_stream_info(state->pFormatCtx, NULL) < 0) {
	    printf("Metadata could not be retrieved\n");
	    avformat_close_input(&state->pFormatCtx);
		*ps = NULL;
    	return FAILURE;
	}

	get_duration(state->pFormatCtx, duration);
	av_dict_set(&state->pFormatCtx->metadata, DURATION, duration, 0);
	
	get_shoutcast_metadata(state->pFormatCtx);

	//av_dump_format(state->pFormatCtx, 0, path, 0);
	
    // Find the first audio and video stream
	for (i = 0; i < state->pFormatCtx->nb_streams; i++) {
		if (state->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0) {
			video_index = i;
		}

		if (state->pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0) {
			audio_index = i;
		}

		set_codec(state->pFormatCtx, i);
	}

	/*if (audio_index >= 0) {
		stream_component_open(state, audio_index);
	}*/

	if (video_index >= 0) {
		stream_component_open(state, video_index);
	}

	/*if(state->video_stream < 0 || state->audio_stream < 0) {
	    avformat_close_input(&state->pFormatCtx);
		*ps = NULL;
		return FAILURE;
	}*/

	/*printf("Found metadata\n");
	AVDictionaryEntry *tag = NULL;
	while ((tag = av_dict_get(state->pFormatCtx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
    	printf("Key %s: \n", tag->key);
    	printf("Value %s: \n", tag->value);
    }*/
	
	*ps = state;
	return SUCCESS;
}