Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
6144 serge 1
#include 
2
 
3
#include 
4
#include 
5
#include 
6
 
7
#include 
8
#include 
9
#include 
10
#include 
11
#include 
12
#include "winlib/winlib.h"
13
 
14
#include "sound.h"
15
#include "fplay.h"
16
 
6658 serge 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
 
6144 serge 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
 
6658 serge 45
    decoder = &ffmpeg_decoder;
6144 serge 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;
6658 serge 79
    decoder->profile  = vCtx->profile;
80
    decoder->fini     = fini_ffmpeg_decoder;
6144 serge 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
 
6658 serge 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