Subversion Repositories Kolibri OS

Rev

Rev 6117 | Rev 6121 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1.  
  2. #include <stdint.h>
  3.  
  4. #include <libavcodec/avcodec.h>
  5. #include <libavformat/avformat.h>
  6. #include <libavdevice/avdevice.h>
  7. #include <libswscale/swscale.h>
  8.  
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <fcntl.h>
  12. #include <ctype.h>
  13. #include <kos32sys.h>
  14. #include "winlib/winlib.h"
  15.  
  16. #include "sound.h"
  17. #include "fplay.h"
  18.  
  19. #ifdef HAVE_VAAPI
  20. int va_check_codec_support(enum AVCodecID id);
  21. #endif
  22.  
  23. volatile enum player_state player_state  = STOP;
  24. volatile enum player_state decoder_state = PREPARE;
  25. volatile enum player_state sound_state   = STOP;
  26.  
  27. uint32_t win_width, win_height;
  28.  
  29.  
  30. AVFrame         *pFrame;
  31.  
  32. int             have_sound = 0;
  33.  
  34. uint8_t     *decoder_buffer;
  35. extern int resampler_size;
  36.  
  37. extern int sample_rate;
  38. char *movie_file;
  39.  
  40. void flush_video(vst_t* vst);
  41.  
  42.  
  43. int64_t  rewind_pos;
  44.  
  45. int64_t stream_duration;
  46.  
  47. int threads_running = DECODER_THREAD;
  48.  
  49. extern double audio_base;
  50.  
  51.  
  52. double get_audio_base(vst_t* vst)
  53. {
  54.     return (double)av_q2d(vst->fCtx->streams[vst->aStream]->time_base)*1000;
  55. };
  56.  
  57.  
  58. int main( int argc, char *argv[])
  59. {
  60.     static vst_t vst;
  61.     int i, ret;
  62.     char *file_name, *dot;
  63.  
  64.     if(argc < 2)
  65.     {
  66.         movie_file = get_moviefile();
  67.         if(movie_file == NULL)
  68.         {
  69.             printf("Please provide a movie file\n");
  70.             return -1;
  71.         }
  72.     }
  73.     else movie_file = argv[1];
  74.  
  75.     /* register all codecs, demux and protocols */
  76.  
  77.     av_log_set_level(AV_LOG_FATAL);
  78.  
  79.     avcodec_register_all();
  80.     avdevice_register_all();
  81.     av_register_all();
  82.  
  83. #ifdef HAVE_VAAPI
  84.     fplay_vaapi_init();
  85. #endif
  86.  
  87.     if( avformat_open_input(&vst.fCtx, movie_file, NULL, NULL) < 0)
  88.     {
  89.         printf("Cannot open file %s\n\r", movie_file);
  90.         return -1; // Couldn't open file
  91.     };
  92.  
  93.     vst.fCtx->flags |= AVFMT_FLAG_GENPTS;
  94.  
  95.   // Retrieve stream information
  96.     if(avformat_find_stream_info(vst.fCtx, NULL) < 0)
  97.     {
  98.         printf("Cannot find streams\n\r");
  99.         return -1;
  100.     };
  101.  
  102.     file_name = strrchr(movie_file,'/')+1;
  103.     dot = strrchr(file_name,'.');
  104.     if(dot)
  105.     {
  106.         movie_file = malloc(dot-file_name+1);
  107.         memcpy(movie_file, file_name, dot-file_name);
  108.         movie_file[dot-file_name] = 0;
  109.     }
  110.     else movie_file = file_name;
  111.  
  112.     stream_duration = vst.fCtx->duration;
  113.  
  114.    // Find the first video stream
  115.     vst.vStream = -1;
  116.     vst.aStream = -1;
  117.  
  118.     for(i=0; i < vst.fCtx->nb_streams; i++)
  119.     {
  120.         if(vst.fCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO
  121.             && vst.vStream < 0)
  122.         {
  123.             vst.vStream = i;
  124.             video_time_base = vst.fCtx->streams[i]->time_base;
  125.             if(stream_duration == 0)
  126.                stream_duration = vst.fCtx->streams[i]->duration;
  127.         }
  128.  
  129.         if(vst.fCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
  130.            vst.aStream < 0)
  131.         {
  132.             vst.aStream = i;
  133.             if(stream_duration == 0)
  134.                stream_duration = vst.fCtx->streams[i]->duration;
  135.         }
  136.     }
  137.  
  138.     if(vst.vStream==-1)
  139.     {
  140.         printf("Video stream not detected\n\r");
  141.         return -1; // Didn't find a video stream
  142.     };
  143.  
  144.   //   __asm__ __volatile__("int3");
  145.  
  146.     // Get a pointer to the codec context for the video stream
  147.     vst.vCtx = vst.fCtx->streams[vst.vStream]->codec;
  148.     vst.aCtx = vst.fCtx->streams[vst.aStream]->codec;
  149.  
  150.     vst.vCodec = avcodec_find_decoder(vst.vCtx->codec_id);
  151.     printf("codec id %x name %s\n",vst.vCtx->codec_id, vst.vCodec->name);
  152.     printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt);
  153.  
  154.     if(vst.vCodec == NULL)
  155.     {
  156.         printf("Unsupported codec with id %d for input stream %d\n",
  157.         vst.vCtx->codec_id, vst.vStream);
  158.         return -1; // Codec not found
  159.     }
  160.  
  161. #ifdef HAVE_VAAPI
  162.     int hwdec = va_check_codec_support(vst.vCtx->codec_id);
  163.  
  164.     if(hwdec)
  165.     {
  166.         printf("hardware decode supported\n");
  167.  
  168.         if (fplay_init_context(&vst) < 0)
  169.         {
  170.             printf("context initialization failed\n");
  171.             return -1;
  172.         };
  173.     };
  174. #endif
  175.  
  176.     if(avcodec_open2(vst.vCtx, vst.vCodec, NULL) < 0)
  177.     {
  178.         printf("Error while opening codec for input stream %d\n",
  179.                 vst.vStream);
  180.         return -1; // Could not open codec
  181.     };
  182.  
  183.  
  184.     mutex_init(&vst.q_video.lock);
  185.     mutex_init(&vst.q_audio.lock);
  186.     mutex_init(&vst.gpu_lock);
  187.  
  188.     if (vst.aCtx->channels > 0)
  189.         vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels);
  190.     else
  191.         vst.aCtx->request_channels = 2;
  192.  
  193.     vst.aCodec = avcodec_find_decoder(vst.aCtx->codec_id);
  194.  
  195.     if(vst.aCodec)
  196.     {
  197.         if(avcodec_open2(vst.aCtx, vst.aCodec, NULL) >= 0 )
  198.         {
  199.             WAVEHEADER       whdr;
  200.             int fmt;
  201.             int channels;
  202.  
  203.             printf("audio stream rate %d channels %d format %d\n",
  204.             vst.aCtx->sample_rate, vst.aCtx->channels, vst.aCtx->sample_fmt );
  205.             whdr.riff_id = 0x46464952;
  206.             whdr.riff_format = 0x45564157;
  207.             whdr.wFormatTag = 0x01;
  208.             whdr.nSamplesPerSec = vst.aCtx->sample_rate;
  209.             whdr.nChannels = 2;
  210.             whdr.wBitsPerSample = 16;
  211.  
  212.             sample_rate = vst.aCtx->sample_rate;
  213.  
  214.             fmt = test_wav(&whdr);
  215.  
  216.             if( init_audio(fmt) )
  217.             {
  218.                 decoder_buffer = (uint8_t*)av_mallocz(192000*2+64);
  219.                 if( decoder_buffer != NULL )
  220.                 {
  221.                     mutex_init(&astream.lock);
  222.                     astream.count  = 0;
  223.                     astream.buffer = (char *)av_mallocz(192000*3);
  224.                     if( astream.buffer != NULL )
  225.                         have_sound = 1;
  226.                     else
  227.                         av_free(decoder_buffer);
  228.                 }
  229.                 if( have_sound == 0)
  230.                 {
  231.                         printf("Not enough memory for audio buffers\n");
  232.                 }
  233.             }
  234.         }
  235.         else printf("Cannot open audio codec\n\r");
  236.     }
  237.     else printf("Unsupported audio codec!\n");
  238.  
  239.     if(!init_video(&vst))
  240.         return 0;
  241.  
  242.     decoder(&vst);
  243.  
  244.   // Free the YUV frame
  245.     av_free(pFrame);
  246.  
  247.  
  248. //__asm__ __volatile__("int3");
  249.  
  250.     while( threads_running &
  251.            (AUDIO_THREAD | VIDEO_THREAD))
  252.            delay(1);
  253.  
  254.     if(astream.lock.handle)
  255.         mutex_destroy(&astream.lock);
  256.  
  257.     mutex_destroy(&vst.q_video.lock);
  258.     mutex_destroy(&vst.q_audio.lock);
  259.  
  260.     return 0;
  261. }
  262.  
  263.  
  264. static int load_frame(vst_t *vst)
  265. {
  266.     AVPacket  packet;
  267.     int err;
  268.  
  269.     err = av_read_frame(vst->fCtx, &packet);
  270.     if( err == 0)
  271.     {
  272.         if(packet.stream_index == vst->vStream)
  273.             put_packet(&vst->q_video, &packet);
  274.         else if( (packet.stream_index == vst->aStream) &&
  275.                   (have_sound != 0) )
  276.         {
  277.             put_packet(&vst->q_audio, &packet);
  278.             if(audio_base == -1.0)
  279.             {
  280.                 if (packet.pts != AV_NOPTS_VALUE)
  281.                     audio_base = get_audio_base(vst) * packet.pts;
  282. //                    printf("audio base %f\n", audio_base);
  283.             };
  284.         }
  285.         else av_free_packet(&packet);
  286.     }
  287.     else if (err != AVERROR_EOF)
  288.         printf("av_read_frame: error %x\n", err);
  289.  
  290.     return err;
  291. }
  292.  
  293.  
  294.  
  295. static int fill_queue(vst_t* vst)
  296. {
  297.     int err = 0;
  298.     AVPacket  packet;
  299.  
  300.     while( (vst->q_video.size < 4*1024*1024) && !err )
  301.         err = load_frame(vst);
  302.  
  303.     return err;
  304. };
  305.  
  306.  
  307. static void flush_all(vst_t* vst)
  308. {
  309.     AVPacket  packet;
  310.  
  311.     avcodec_flush_buffers(vst->vCtx);
  312.     avcodec_flush_buffers(vst->aCtx);
  313.     while( get_packet(&vst->q_video, &packet) != 0)
  314.         av_free_packet(&packet);
  315.  
  316.     while( get_packet(&vst->q_audio, &packet)!= 0)
  317.         av_free_packet(&packet);
  318.  
  319.     flush_video(vst);
  320.  
  321.     astream.count = 0;
  322. };
  323.  
  324. void decoder(vst_t* vst)
  325. {
  326.     int       eof;
  327.     AVPacket  packet;
  328.     int       ret, vret, aret;
  329.  
  330.     int64_t   min_pos, max_pos;
  331.  
  332. //    av_log_set_level(AV_LOG_DEBUG);
  333.  
  334.     while( player_state != CLOSED )
  335.     {
  336.         int err;
  337.  
  338.         switch(decoder_state)
  339.         {
  340.             case PREPARE:
  341.                 eof = fill_queue(vst);
  342.  
  343.                 do
  344.                 {
  345.                     if( (vst->q_video.size < 4*1024*1024) &&
  346.                         (eof == 0) )
  347.                     {
  348.                         eof = load_frame(vst);
  349.                     }
  350.                     decode_video(vst);
  351.                     ret = decode_audio(vst->aCtx, &vst->q_audio);
  352.                 }while(astream.count < resampler_size*2 &&
  353.                        ret == 1);
  354.  
  355.                 sound_state   = PREPARE;
  356.                 decoder_state = PLAY;
  357.                 player_state  = PLAY;
  358.  
  359.             case PLAY:
  360.                 if( (vst->q_video.size < 4*1024*1024) &&
  361.                     (eof == 0) )
  362.                 {
  363.                     eof = load_frame(vst);
  364.                 }
  365.                 vret = decode_video(vst);
  366.                 aret = decode_audio(vst->aCtx, &vst->q_audio);
  367.                 ret = vret | aret;
  368.  
  369.                 if( eof && !ret)
  370.                 {
  371.                     decoder_state = STOP;
  372.                     continue;
  373.                 };
  374.  
  375.                 if( (vret & aret) == -1)
  376.                 {
  377.                     if( (vst->q_video.size < 4*1024*1024) &&
  378.                         (eof == 0) )
  379.                     {
  380.                         eof = load_frame(vst);
  381.                         yield();
  382.                         continue;
  383.                     };
  384.                     delay(1);
  385.                     continue;
  386.                 }
  387.  
  388.                 yield();
  389.                 continue;
  390.  
  391.             case STOP:
  392.                 delay(1);
  393.                 continue;
  394.  
  395.  
  396.             case PLAY_2_STOP:
  397.                 while(sound_state != STOP)
  398.                     delay(1);
  399.  
  400.                 flush_all(vst);
  401.  
  402.                 if (vst->fCtx->start_time != AV_NOPTS_VALUE)
  403.                     rewind_pos = vst->fCtx->start_time;
  404.                 else
  405.                     rewind_pos = 0;
  406.  
  407.                 ret = avformat_seek_file(vst->fCtx, -1, INT64_MIN,
  408.                                          rewind_pos, INT64_MAX, 0);
  409.  
  410.                 decoder_state = STOP;
  411.                 break;
  412.  
  413.             case REWIND:
  414.                 while(sound_state != STOP)
  415.                     yield();
  416.  
  417.                 flush_all(vst);
  418.                 int opts = 0;
  419.                 if(rewind_pos < 0)
  420.                 {
  421.                     rewind_pos = -rewind_pos;
  422.                     opts = AVSEEK_FLAG_BACKWARD;
  423.                 };
  424.  
  425.                 if (vst->fCtx->start_time != AV_NOPTS_VALUE)
  426.                     rewind_pos += vst->fCtx->start_time;
  427.  
  428. //                printf("rewind %8"PRId64"\n", rewind_pos);
  429.                 min_pos = rewind_pos - 1000000;
  430.                 max_pos = rewind_pos + 1000000;
  431.  
  432.                 ret = avformat_seek_file(vst->fCtx, -1, INT64_MIN,
  433.                                          rewind_pos, INT64_MAX, 0);
  434.                 if (ret < 0)
  435.                 {
  436.                     printf("could not seek to position %f\n",
  437.                             (double)rewind_pos / AV_TIME_BASE);
  438.                 }
  439.                 decoder_state = PREPARE;
  440.                 break;
  441.         }
  442.     };
  443. };
  444.  
  445.