Subversion Repositories Kolibri OS

Rev

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