Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | 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
 
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