Subversion Repositories Kolibri OS

Rev

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