Subversion Repositories Kolibri OS

Rev

Rev 6144 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include <stdint.h>
  2.  
  3. #include <libavcodec/avcodec.h>
  4. #include <libavformat/avformat.h>
  5. #include <libavutil/imgutils.h>
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <fcntl.h>
  10. #include <ctype.h>
  11. #include <kos32sys.h>
  12. #include "winlib/winlib.h"
  13.  
  14. #include "sound.h"
  15. #include "fplay.h"
  16.  
  17. static struct decoder ffmpeg_decoder;
  18. static struct decoder* init_ffmpeg_decoder(vst_t *vst);
  19.  
  20. static decoder_init_fn* decoders[] = {
  21.     init_va_decoder,
  22.     init_ffmpeg_decoder,
  23.     NULL
  24. };
  25.  
  26. static void fini_ffmpeg_decoder(vst_t *vst)
  27. {
  28.     av_frame_free(&vst->decoder->Frame);
  29.  
  30.     for(int i = 0; i < vst->decoder->nframes; i++)
  31.     {
  32.         vframe_t *vframe;
  33.         vframe = &vst->decoder->vframes[i];
  34.         avpicture_free(&vframe->picture);
  35.     };
  36. };
  37.  
  38. static struct decoder* init_ffmpeg_decoder(vst_t *vst)
  39. {
  40.     AVCodecContext *vCtx = vst->vCtx;
  41.     struct decoder *decoder;
  42.     vframe_t *vframe;
  43.     int i, ret;
  44.  
  45.     decoder = &ffmpeg_decoder;
  46.  
  47.     decoder->Frame = av_frame_alloc();
  48.     if(decoder->Frame == NULL)
  49.         goto err_0;
  50.  
  51.     decoder->nframes = 4;
  52.  
  53.     for(i = 0; i < decoder->nframes; i++)
  54.     {
  55.         vframe = &decoder->vframes[i];
  56.  
  57.         ret = avpicture_alloc(&vframe->picture, vCtx->pix_fmt,
  58.                                vCtx->width, vCtx->height);
  59.         if ( ret != 0 )
  60.             goto err_1;
  61.  
  62.         vframe->format = vCtx->pix_fmt;
  63.         vframe->index  = i;
  64.         list_add_tail(&vframe->list, &vst->input_list);
  65.     };
  66.  
  67.     if(avcodec_open2(vCtx, vst->vCodec, NULL) < 0)
  68.     {
  69.         printf("Error while opening codec for input stream %d\n",
  70.                 vst->vStream);
  71.         goto err_1;
  72.     };
  73.  
  74.     decoder->name     = vst->vCodec->name;
  75.     decoder->pix_fmt  = vCtx->pix_fmt;
  76.     decoder->width    = vCtx->width;
  77.     decoder->height   = vCtx->height;
  78.     decoder->codec_id = vCtx->codec_id;
  79.     decoder->profile  = vCtx->profile;
  80.     decoder->fini     = fini_ffmpeg_decoder;
  81.     return decoder;
  82.  
  83. err_1:
  84.     for(i = i-1; i >= 0; i--)
  85.     {
  86.         vframe = &decoder->vframes[i];
  87.         avpicture_free(&vframe->picture);
  88.     };
  89. err_0:
  90.     return NULL;
  91. }
  92.  
  93. static vframe_t *get_input_frame(vst_t *vst)
  94. {
  95.     vframe_t *vframe = NULL;
  96.  
  97.     mutex_lock(&vst->input_lock);
  98.     if(!list_empty(&vst->input_list))
  99.     {
  100.         vframe = list_first_entry(&vst->input_list, vframe_t, list);
  101.         list_del(&vframe->list);
  102.     }
  103.     mutex_unlock(&vst->input_lock);
  104.  
  105.     return vframe;
  106. }
  107.  
  108. static void put_output_frame(vst_t *vst, vframe_t *vframe)
  109. {
  110.     mutex_lock(&vst->output_lock);
  111.     if(list_empty(&vst->output_list))
  112.         list_add_tail(&vframe->list, &vst->output_list);
  113.     else
  114.     {
  115.         vframe_t *cur;
  116.  
  117.         cur = list_first_entry(&vst->output_list,vframe_t,list);
  118.         if(vframe->pts < cur->pts)
  119.             list_add_tail(&vframe->list, &vst->output_list);
  120.         else
  121.         {
  122.             list_for_each_entry_reverse(cur,&vst->output_list,list)
  123.             {
  124.                 if(vframe->pts > cur->pts)
  125.                 {
  126.                     list_add(&vframe->list, &cur->list);
  127.                     break;
  128.                 };
  129.             };
  130.         };
  131.     };
  132.     vst->frames_count++;
  133.     mutex_unlock(&vst->output_lock);
  134. };
  135.  
  136. int decode_video(vst_t* vst)
  137. {
  138.     struct decoder* decoder = vst->decoder;
  139.     double     pts;
  140.     AVPacket   pkt;
  141.  
  142.     int frameFinished;
  143.  
  144.     if(decoder->active_frame == NULL)
  145.         decoder->active_frame = get_input_frame(vst);
  146.  
  147.     if(decoder->active_frame == NULL)
  148.         return -1;
  149.  
  150.     if( get_packet(&vst->q_video, &pkt) == 0 )
  151.         return 0;
  152.  
  153.     frameFinished = 0;
  154.  
  155.     mutex_lock(&vst->gpu_lock);
  156.  
  157.     if(avcodec_decode_video2(vst->vCtx, decoder->Frame, &frameFinished, &pkt) <= 0)
  158.         printf("video decoder error\n");
  159.  
  160.     if(frameFinished)
  161.     {
  162.         vframe_t  *vframe = decoder->active_frame;
  163.         AVPicture *dst_pic;
  164.  
  165.         if(decoder->is_hw)
  166.             pts = pkt.pts;
  167.         else
  168.             pts = av_frame_get_best_effort_timestamp(decoder->Frame);
  169.  
  170.         pts*= av_q2d(vst->video_time_base);
  171.  
  172.         dst_pic = &vframe->picture;
  173.  
  174.         if(vframe->is_hw_pic == 0)
  175.             av_image_copy(dst_pic->data, dst_pic->linesize,
  176.                           (const uint8_t**)decoder->Frame->data,
  177.                           decoder->Frame->linesize, vst->vCtx->pix_fmt, vst->vCtx->width, vst->vCtx->height);
  178.         else
  179.             va_create_planar(vst, vframe);
  180.  
  181.         vframe->pts = pts*1000.0;
  182.         vframe->pkt_pts = pkt.pts*av_q2d(vst->video_time_base)*1000.0;
  183.         vframe->ready = 1;
  184.  
  185.         put_output_frame(vst, vframe);
  186.  
  187. //        printf("decoded index: %d pts: %f pkt_pts %f pkt_dts %f\n",
  188. //               vst->dfx, vst->vframe[vst->dfx].pts,
  189. //               vst->vframe[vst->dfx].pkt_pts, vst->vframe[vst->dfx].pkt_dts);
  190.  
  191.         decoder->active_frame = NULL;
  192.     };
  193.     av_frame_unref(decoder->Frame);
  194.     mutex_unlock(&vst->gpu_lock);
  195.  
  196.     av_free_packet(&pkt);
  197.  
  198.     return 1;
  199. }
  200.  
  201. int init_video_decoder(vst_t *vst)
  202. {
  203.     decoder_init_fn **init_fn;
  204.     AVCodecContext *vCtx = vst->vCtx;
  205.     int i;
  206.  
  207.     vst->vCodec = avcodec_find_decoder(vCtx->codec_id);
  208.  
  209.     if(vst->vCodec == NULL)
  210.     {
  211.         printf("Unsupported codec with id %d for input stream %d\n",
  212.         vst->vCtx->codec_id, vst->vStream);
  213.         return -1;
  214.     }
  215.  
  216.     for(init_fn = decoders; init_fn != NULL; init_fn++)
  217.     {
  218.         vst->decoder = (*init_fn)(vst);
  219.         if(vst->decoder != NULL)
  220.         {
  221.             printf("%dx%d %s %s%s decoder\n",
  222.                     vst->decoder->width, vst->decoder->height,
  223.                     av_get_pix_fmt_name(vst->decoder->pix_fmt),
  224.                     vst->decoder->is_hw == 0 ? "ffmpeg ":"vaapi ",
  225.                     vst->decoder->name);
  226.  
  227.             return 0;
  228.         };
  229.     }
  230.  
  231.     return -1;
  232. }
  233.  
  234.