Subversion Repositories Kolibri OS

Rev

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