| | 3122 | bool AvFormatDecoder::PreProcessVideoPacket(AVPacket *pkt, AVStream *stream) |
| | 3123 | { |
| | 3124 | |
| | 3125 | AVCodecContext *ctx = stream->codec; |
| | 3126 | bool on_frame = true; |
| | 3127 | |
| | 3128 | if (CODEC_IS_FFMPEG_MPEG(ctx->codec_id)) |
| | 3129 | { |
| | 3130 | if (!ringBuffer->isDVD()) |
| | 3131 | MpegPreProcessPkt(stream, pkt); |
| | 3132 | } |
| | 3133 | else if (CODEC_IS_H264(ctx->codec_id)) |
| | 3134 | on_frame = H264PreProcessPkt(stream, pkt); |
| | 3135 | else |
| | 3136 | { |
| | 3137 | if (pkt->flags & PKT_FLAG_KEY) |
| | 3138 | { |
| | 3139 | HandleGopStart(pkt, false); |
| | 3140 | seen_gop = true; |
| | 3141 | } |
| | 3142 | else |
| | 3143 | { |
| | 3144 | seq_count++; |
| | 3145 | if (!seen_gop && seq_count > 1) |
| | 3146 | HandleGopStart(pkt, false); |
| | 3147 | } |
| | 3148 | } |
| | 3149 | |
| | 3150 | if (framesRead == 0 && !justAfterChange && !(pkt->flags & PKT_FLAG_KEY)) |
| | 3151 | { |
| | 3152 | av_free_packet(pkt); |
| | 3153 | return false; |
| | 3154 | } |
| | 3155 | |
| | 3156 | if (on_frame) |
| | 3157 | framesRead++; |
| | 3158 | justAfterChange = false; |
| | 3159 | |
| | 3160 | if (exitafterdecoded) |
| | 3161 | gotvideo = 1; |
| | 3162 | |
| | 3163 | return true; |
| | 3164 | } |
| | 3165 | |
| | 3166 | int AvFormatDecoder::ProcessVideoPacket(const AVPacket *pkt, |
| | 3167 | const AVStream *stream, |
| | 3168 | long long pts, bool firstloop) |
| | 3169 | { |
| | 3170 | AVCodecContext *ctx = stream->codec; |
| | 3171 | uchar *ptr = pkt->data; |
| | 3172 | int len = pkt->size; |
| | 3173 | int ret = 0; |
| | 3174 | |
| | 3175 | if (pkt->stream_index != selectedVideoIndex) |
| | 3176 | return len; |
| | 3177 | |
| | 3178 | if (firstloop && pts != (int64_t) AV_NOPTS_VALUE) |
| | 3179 | lastccptsu = (long long) |
| | 3180 | (av_q2d(stream->time_base) * pkt->pts * 1000000); |
| | 3181 | |
| | 3182 | if (!wantvideo) |
| | 3183 | { |
| | 3184 | framesPlayed++; |
| | 3185 | gotvideo = 1; |
| | 3186 | return len; |
| | 3187 | } |
| | 3188 | |
| | 3189 | AVFrame mpa_pic; |
| | 3190 | bzero(&mpa_pic, sizeof(AVFrame)); |
| | 3191 | |
| | 3192 | int gotpicture = 0; |
| | 3193 | |
| | 3194 | avcodeclock->lock(); |
| | 3195 | if (d->HasDecoder()) |
| | 3196 | { |
| | 3197 | if (decodeStillFrame) |
| | 3198 | { |
| | 3199 | int count = 0; |
| | 3200 | // HACK |
| | 3201 | while (!gotpicture && count < 5) |
| | 3202 | { |
| | 3203 | ret = d->DecodeMPEG2Video(ctx, &mpa_pic, &gotpicture, ptr, len); |
| | 3204 | count++; |
| | 3205 | } |
| | 3206 | } |
| | 3207 | else |
| | 3208 | ret = d->DecodeMPEG2Video(ctx, &mpa_pic, &gotpicture, ptr, len); |
| | 3209 | } |
| | 3210 | else |
| | 3211 | { |
| | 3212 | ret = avcodec_decode_video(ctx, &mpa_pic, &gotpicture, ptr, len); |
| | 3213 | // Reparse it to not drop the DVD still frame |
| | 3214 | if (decodeStillFrame) |
| | 3215 | ret = avcodec_decode_video(ctx, &mpa_pic, &gotpicture, ptr, len); |
| | 3216 | } |
| | 3217 | avcodeclock->unlock(); |
| | 3218 | |
| | 3219 | if (ret < 0) |
| | 3220 | { |
| | 3221 | VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown decoding error"); |
| | 3222 | return len; |
| | 3223 | } |
| | 3224 | |
| | 3225 | if (!gotpicture) |
| | 3226 | return len; |
| | 3227 | |
| | 3228 | // Decode CEA-608 and CEA-708 captions |
| | 3229 | for (uint i = 0; i < (uint)mpa_pic.atsc_cc_len; |
| | 3230 | i += ((mpa_pic.atsc_cc_buf[i] & 0x1f) * 3) + 2) |
| | 3231 | DecodeDTVCC(mpa_pic.atsc_cc_buf + i, mpa_pic.atsc_cc_len - i); |
| | 3232 | |
| | 3233 | VideoFrame *picframe = (VideoFrame *)(mpa_pic.opaque); |
| | 3234 | |
| | 3235 | if (!directrendering) |
| | 3236 | { |
| | 3237 | AVPicture tmppicture; |
| | 3238 | |
| | 3239 | VideoFrame *xf = picframe; |
| | 3240 | picframe = GetNVP()->GetNextVideoFrame(false); |
| | 3241 | |
| | 3242 | unsigned char *buf = picframe->buf; |
| | 3243 | avpicture_fill(&tmppicture, buf, PIX_FMT_YUV420P, |
| | 3244 | ctx->width, ctx->height); |
| | 3245 | tmppicture.data[0] = buf + picframe->offsets[0]; |
| | 3246 | tmppicture.data[1] = buf + picframe->offsets[1]; |
| | 3247 | tmppicture.data[2] = buf + picframe->offsets[2]; |
| | 3248 | tmppicture.linesize[0] = picframe->pitches[0]; |
| | 3249 | tmppicture.linesize[1] = picframe->pitches[1]; |
| | 3250 | tmppicture.linesize[2] = picframe->pitches[2]; |
| | 3251 | |
| | 3252 | sws_ctx = sws_getCachedContext(sws_ctx, ctx->width, |
| | 3253 | ctx->height, ctx->pix_fmt, |
| | 3254 | ctx->width, ctx->height, |
| | 3255 | PIX_FMT_YUV420P, SWS_FAST_BILINEAR, |
| | 3256 | NULL, NULL, NULL); |
| | 3257 | if (!sws_ctx) |
| | 3258 | { |
| | 3259 | VERBOSE(VB_IMPORTANT, LOC_ERR + |
| | 3260 | "Failed to allocate sws context"); |
| | 3261 | return -1; |
| | 3262 | } |
| | 3263 | sws_scale(sws_ctx, mpa_pic.data, mpa_pic.linesize, |
| | 3264 | 0, ctx->height, tmppicture.data, |
| | 3265 | tmppicture.linesize); |
| | 3266 | |
| | 3267 | if (xf) |
| | 3268 | { |
| | 3269 | // Set the frame flags, but then discard it |
| | 3270 | // since we are not using it for display. |
| | 3271 | xf->interlaced_frame = mpa_pic.interlaced_frame; |
| | 3272 | xf->top_field_first = mpa_pic.top_field_first; |
| | 3273 | xf->frameNumber = framesPlayed; |
| | 3274 | GetNVP()->DiscardVideoFrame(xf); |
| | 3275 | } |
| | 3276 | } |
| | 3277 | |
| | 3278 | long long temppts = pts; |
| | 3279 | |
| | 3280 | // Validate the video pts against the last pts. If it's |
| | 3281 | // a little bit smaller, equal or not available, compute |
| | 3282 | // it from the last. Otherwise assume a wraparound. |
| | 3283 | if (!ringBuffer->isDVD() && temppts <= lastvpts && |
| | 3284 | (temppts + 10000 > lastvpts || temppts <= 0)) |
| | 3285 | { |
| | 3286 | temppts = lastvpts; |
| | 3287 | temppts += (long long)(1000 / fps); |
| | 3288 | // MPEG2/H264 frames can be repeated, update pts accordingly |
| | 3289 | temppts += (long long)(mpa_pic.repeat_pict * 500 / fps); |
| | 3290 | } |
| | 3291 | |
| | 3292 | VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + |
| | 3293 | QString("video timecode %1 %2 %3 %4") |
| | 3294 | .arg(pkt->pts).arg(pkt->dts).arg(temppts).arg(lastvpts)); |
| | 3295 | |
| | 3296 | /* XXX: Broken. |
| | 3297 | if (mpa_pic.qscale_table != NULL && mpa_pic.qstride > 0 && |
| | 3298 | context->height == picframe->height) |
| | 3299 | { |
| | 3300 | int tblsize = mpa_pic.qstride * |
| | 3301 | ((picframe->height + 15) / 16); |
| | 3302 | |
| | 3303 | if (picframe->qstride != mpa_pic.qstride || |
| | 3304 | picframe->qscale_table == NULL) |
| | 3305 | { |
| | 3306 | picframe->qstride = mpa_pic.qstride; |
| | 3307 | if (picframe->qscale_table) |
| | 3308 | delete [] picframe->qscale_table; |
| | 3309 | picframe->qscale_table = new unsigned char[tblsize]; |
| | 3310 | } |
| | 3311 | |
| | 3312 | memcpy(picframe->qscale_table, mpa_pic.qscale_table, |
| | 3313 | tblsize); |
| | 3314 | } |
| | 3315 | */ |
| | 3316 | |
| | 3317 | picframe->interlaced_frame = mpa_pic.interlaced_frame; |
| | 3318 | picframe->top_field_first = mpa_pic.top_field_first; |
| | 3319 | picframe->repeat_pict = mpa_pic.repeat_pict; |
| | 3320 | picframe->frameNumber = framesPlayed; |
| | 3321 | |
| | 3322 | GetNVP()->ReleaseNextVideoFrame(picframe, temppts); |
| | 3323 | if (d->HasMPEG2Dec() && mpa_pic.data[3]) |
| | 3324 | ctx->release_buffer(ctx, &mpa_pic); |
| | 3325 | |
| | 3326 | decoded_video_frame = picframe; |
| | 3327 | gotvideo = true; |
| | 3328 | lastvpts = temppts; |
| | 3329 | framesPlayed++; |
| | 3330 | |
| | 3331 | return ret; |
| | 3332 | |
| | 3333 | } |
| | 3334 | |
| | 3335 | static void extract_mono_channel(uint channel, AudioInfo *audioInfo, |
| | 3336 | char *buffer, int bufsize) |
| | 3337 | { |
| | 3338 | // Only stereo -> mono (left or right) is supported |
| | 3339 | if (audioInfo->channels != 2) |
| | 3340 | return; |
| | 3341 | |
| | 3342 | if (channel >= (uint)audioInfo->channels) |
| | 3343 | return; |
| | 3344 | |
| | 3345 | const uint samplesize = audioInfo->sample_size; |
| | 3346 | const uint samples = bufsize / samplesize; |
| | 3347 | const uint halfsample = samplesize >> 1; |
| | 3348 | |
| | 3349 | const char *from = (channel == 1) ? buffer + halfsample : buffer; |
| | 3350 | char *to = (channel == 0) ? buffer + halfsample : buffer; |
| | 3351 | |
| | 3352 | for (uint sample = 0; sample < samples; |
| | 3353 | (sample++), (from += samplesize), (to += samplesize)) |
| | 3354 | { |
| | 3355 | memmove(to, from, halfsample); |
| | 3356 | } |
| | 3357 | } |
| | 3358 | |
| | 3359 | int AvFormatDecoder::ProcessAudioPacket(const AVPacket *pkt, |
| | 3360 | const AVStream *stream, |
| | 3361 | uchar *ptr, int len, int &decoded, |
| | 3362 | bool firstloop) |
| | 3363 | { |
| | 3364 | AVCodecContext *ctx = stream->codec; |
| | 3365 | int ret = 0; |
| | 3366 | bool reselectAudioTrack = false, dts = false; |
| | 3367 | AC3HeaderInfo hdr; |
| | 3368 | char *s; |
| | 3369 | |
| | 3370 | avcodeclock->lock(); |
| | 3371 | int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index; |
| | 3372 | int audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index; |
| | 3373 | avcodeclock->unlock(); |
| | 3374 | /// HACK HACK HACK -- begin See #3731 |
| | 3375 | if (!GetNVP()->HasAudioIn()) |
| | 3376 | { |
| | 3377 | VERBOSE(VB_AUDIO, LOC + "Audio is disabled - trying to restart it"); |
| | 3378 | reselectAudioTrack = true; |
| | 3379 | } |
| | 3380 | /// HACK HACK HACK -- end |
| | 3381 | |
| | 3382 | // detect switches between stereo and dual languages |
| | 3383 | bool wasDual = audSubIdx != -1; |
| | 3384 | bool isDual = ctx->avcodec_dual_language; |
| | 3385 | if ((wasDual && !isDual) || (!wasDual && isDual)) |
| | 3386 | { |
| | 3387 | SetupAudioStreamSubIndexes(audIdx); |
| | 3388 | reselectAudioTrack = true; |
| | 3389 | } |
| | 3390 | |
| | 3391 | // detect channels on streams that need |
| | 3392 | // to be decoded before we can know this |
| | 3393 | bool already_decoded = false; |
| | 3394 | if (!ctx->channels) |
| | 3395 | { |
| | 3396 | QMutexLocker locker(avcodeclock); |
| | 3397 | VERBOSE(VB_IMPORTANT, |
| | 3398 | LOC + QString("Setting channels to %1") |
| | 3399 | .arg(audioOut.channels)); |
| | 3400 | |
| | 3401 | if (DoPassThrough(ctx)) |
| | 3402 | ctx->channels = ctx->request_channels = 0; |
| | 3403 | else |
| | 3404 | ctx->channels = ctx->request_channels = audioOut.channels; |
| | 3405 | |
| | 3406 | decoded = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
| | 3407 | ret = avcodec_decode_audio2(ctx, audioSamples, &decoded, ptr, len); |
| | 3408 | already_decoded = true; |
| | 3409 | reselectAudioTrack |= ctx->channels; |
| | 3410 | } |
| | 3411 | |
| | 3412 | if (ctx->codec_id == CODEC_ID_AC3) |
| | 3413 | { |
| | 3414 | GetBitContext gbc; |
| | 3415 | init_get_bits(&gbc, ptr, len << 3); |
| | 3416 | if (!ff_ac3_parse_header(&gbc, &hdr) && |
| | 3417 | hdr.channels != last_ac3_channels) |
| | 3418 | { |
| | 3419 | VERBOSE(VB_AUDIO, LOC + |
| | 3420 | QString("AC3 changed from %1 to %2 channels (frame %3)") |
| | 3421 | .arg(last_ac3_channels).arg(hdr.channels).arg(framesRead)); |
| | 3422 | |
| | 3423 | if ((framesRead - last_framesRead) > AUDIOMAXFRAMES || |
| | 3424 | hdr.channels < last_ac3_channels) |
| | 3425 | { |
| | 3426 | ctx->channels = hdr.channels; |
| | 3427 | } |
| | 3428 | |
| | 3429 | last_ac3_channels = hdr.channels; |
| | 3430 | last_framesRead = framesRead; |
| | 3431 | SetupAudioStream(); |
| | 3432 | } |
| | 3433 | } |
| | 3434 | |
| | 3435 | if (reselectAudioTrack) |
| | 3436 | { |
| | 3437 | QMutexLocker locker(avcodeclock); |
| | 3438 | currentTrack[kTrackTypeAudio] = -1; |
| | 3439 | selectedTrack[kTrackTypeAudio].av_stream_index = -1; |
| | 3440 | audIdx = audSubIdx = -1; |
| | 3441 | AutoSelectAudioTrack(); |
| | 3442 | audIdx = selectedTrack[kTrackTypeAudio].av_stream_index; |
| | 3443 | audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index; |
| | 3444 | } |
| | 3445 | |
| | 3446 | if (!wantaudio || pkt->stream_index != audIdx) |
| | 3447 | { |
| | 3448 | decoded = 0; |
| | 3449 | return len; |
| | 3450 | } |
| | 3451 | |
| | 3452 | if (firstloop && pkt->pts != (int64_t)AV_NOPTS_VALUE) |
| | 3453 | lastapts = (long long)(av_q2d(stream->time_base) * pkt->pts * 1000); |
| | 3454 | |
| | 3455 | if (skipaudio) |
| | 3456 | { |
| | 3457 | if ((lastapts < lastvpts - (10.0 / fps)) || lastvpts == 0) |
| | 3458 | { |
| | 3459 | decoded = 0; |
| | 3460 | return len; |
| | 3461 | } |
| | 3462 | else |
| | 3463 | skipaudio = false; |
| | 3464 | } |
| | 3465 | |
| | 3466 | avcodeclock->lock(); |
| | 3467 | decoded = 0; |
| | 3468 | |
| | 3469 | if (audioOut.do_passthru) |
| | 3470 | { |
| | 3471 | decoded = pkt->size; |
| | 3472 | dts = CODEC_ID_DTS == ctx->codec_id; |
| | 3473 | ret = encode_frame(dts, ptr, len, audioSamples, decoded); |
| | 3474 | s = (char *)audioSamples; |
| | 3475 | } |
| | 3476 | else |
| | 3477 | { |
| | 3478 | if (!ctx->channels || ctx->channels > audioOut.channels) |
| | 3479 | ctx->channels = audioOut.channels; |
| | 3480 | |
| | 3481 | if (!already_decoded) |
| | 3482 | { |
| | 3483 | ctx->request_channels = audioOut.channels; |
| | 3484 | decoded = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
| | 3485 | ret = avcodec_decode_audio2(ctx, audioSamples, &decoded, ptr, len); |
| | 3486 | } |
| | 3487 | |
| | 3488 | // Convert sample format if required (Myth only handles 8 and 16 bits audio) |
| | 3489 | if (ctx->sample_fmt == SAMPLE_FMT_S16 || |
| | 3490 | ctx->sample_fmt == SAMPLE_FMT_U8 || |
| | 3491 | (s = ConvertSampleFormat(ctx, decoded)) == NULL) |
| | 3492 | { |
| | 3493 | s = (char *)audioSamples; |
| | 3494 | } |
| | 3495 | // When decoding some audio streams the number of |
| | 3496 | // channels, etc isn't known until we try decoding it. |
| | 3497 | if ((ctx->sample_rate != audioOut.sample_rate) || |
| | 3498 | (ctx->channels != audioOut.channels)) |
| | 3499 | { |
| | 3500 | VERBOSE(VB_IMPORTANT, LOC + "Audio stream changed"); |
| | 3501 | currentTrack[kTrackTypeAudio] = -1; |
| | 3502 | selectedTrack[kTrackTypeAudio].av_stream_index = -1; |
| | 3503 | audIdx = -1; |
| | 3504 | decoded = 0; |
| | 3505 | AutoSelectAudioTrack(); |
| | 3506 | } |
| | 3507 | } |
| | 3508 | avcodeclock->unlock(); |
| | 3509 | |
| | 3510 | if (ret < 0) |
| | 3511 | { |
| | 3512 | if (!dts) |
| | 3513 | VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown audio decoding error"); |
| | 3514 | decoded = 0; |
| | 3515 | return len; |
| | 3516 | } |
| | 3517 | |
| | 3518 | if (decoded <= 0) |
| | 3519 | return ret; |
| | 3520 | |
| | 3521 | long long temppts = lastapts; |
| | 3522 | |
| | 3523 | // calc for next frame |
| | 3524 | lastapts += (long long)((double)(decoded * 1000) / |
| | 3525 | (ctx->sample_rate * ctx->channels * |
| | 3526 | av_get_bits_per_sample_format(ctx->sample_fmt)>>3)); |
| | 3527 | |
| | 3528 | VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, |
| | 3529 | LOC + QString("audio timecode %1 %2 %3 %4") |
| | 3530 | .arg(pkt->pts).arg(pkt->dts).arg(temppts).arg(lastapts)); |
| | 3531 | |
| | 3532 | if (audSubIdx != -1) |
| | 3533 | extract_mono_channel(audSubIdx, &audioOut, s, decoded); |
| | 3534 | |
| | 3535 | GetNVP()->AddAudioData(s, decoded, temppts); |
| | 3536 | |
| | 3537 | return ret; |
| | 3538 | |
| | 3539 | } |
| | 3540 | |
| | 3541 | bool AvFormatDecoder::TopUpAudioBuffer(int decoded, uint total_decoded, |
| | 3542 | uint ofill, uint othresh) |
| | 3543 | { |
| | 3544 | uint fill, total; |
| | 3545 | |
| | 3546 | if (ofill + total_decoded > othresh) |
| | 3547 | return true; |
| | 3548 | |
| | 3549 | if (!GetNVP()->GetAudioBufferStatus(fill, total)) |
| | 3550 | { |
| | 3551 | VERBOSE(VB_IMPORTANT, LOC_ERR + "GetFrame() : Failed to top off " |
| | 3552 | "buffers in audio only mode"); |
| | 3553 | return false; |
| | 3554 | } |
| | 3555 | |
| | 3556 | total /= 6; // HACK needed for some audio files |
| | 3557 | return (fill == 0) || (fill > (total>>1)) || |
| | 3558 | ((total - fill) < (uint)decoded) || |
| | 3559 | (ofill + total_decoded > (total>>2)) || |
| | 3560 | ((total - fill) < (uint)decoded * 2); |
| | 3561 | } |
| | 3562 | |
| 3896 | | pts = (long long)(av_q2d(curstream->time_base) * pkt->dts * 1000); |
| 3897 | | |
| 3898 | | if (ringBuffer->isDVD() && |
| 3899 | | curstream->codec->codec_type == CODEC_TYPE_VIDEO) |
| 3900 | | { |
| 3901 | | MpegPreProcessPkt(curstream, pkt); |
| | 4339 | pts = (long long)(av_q2d(stream->time_base) * pkt->dts * 1000); |
| | 4340 | |
| | 4341 | if (len <= 0) |
| | 4342 | { |
| | 4343 | av_free_packet(pkt); |
| | 4344 | continue; |
| | 4345 | } |
| | 4346 | |
| | 4347 | if (ctx->codec_type == CODEC_TYPE_VIDEO) |
| | 4348 | { |
| | 4349 | if (ringBuffer->isDVD() && !PreProcessDVDVideoPacket(pkt, stream)) |
| | 4350 | continue; |
| | 4351 | |
| | 4352 | if (storevideoframes) |
| | 4353 | { |
| | 4354 | av_dup_packet(pkt); |
| | 4355 | storedPackets.append(pkt); |
| | 4356 | pkt = NULL; |
| | 4357 | continue; |
| | 4358 | } |
| | 4359 | |
| | 4360 | if (pkt->stream_index == selectedVideoIndex) |
| | 4361 | { |
| | 4362 | if (!PreProcessVideoPacket(pkt, stream)) |
| | 4363 | continue; |
| | 4364 | // If the resolution changed in XXXPreProcessPkt, we may |
| | 4365 | // have a fatal error, so check for this before continuing. |
| | 4366 | if (GetNVP()->IsErrored()) |
| | 4367 | { |
| | 4368 | av_free_packet(pkt); |
| | 4369 | delete pkt; |
| | 4370 | return false; |
| | 4371 | } |
| | 4372 | } |
| | 4373 | } |
| | 4374 | else if ((ctx->codec_type == CODEC_TYPE_DATA || |
| | 4375 | ctx->codec_type == CODEC_TYPE_SUBTITLE) && |
| | 4376 | ProcessDataPacket(pkt, stream)) |
| | 4377 | continue; |
| | 4378 | |
| | 4379 | if (!ctx->codec) |
| | 4380 | { |
| | 4381 | VERBOSE(VB_PLAYBACK, LOC + |
| | 4382 | QString("No codec for stream index %1, type(%2) id(%3:%4)") |
| | 4383 | .arg(pkt->stream_index) |
| | 4384 | .arg(codec_type_string(ctx->codec_type)) |
| | 4385 | .arg(codec_id_string(ctx->codec_id)) |
| | 4386 | .arg(ctx->codec_id)); |
| | 4387 | av_free_packet(pkt); |
| | 4388 | continue; |
| | 4389 | } |
| | 4390 | |
| | 4391 | int ctype = ctx->codec_type; |
| | 4392 | firstloop = true; |
| | 4393 | |
| | 4394 | while (len > 0) |
| | 4395 | { |
| | 4396 | switch (ctype) |
| | 4397 | { |
| | 4398 | case CODEC_TYPE_AUDIO: |
| | 4399 | int decoded; |
| | 4400 | ret = ProcessAudioPacket(pkt, stream, ptr, len, |
| | 4401 | decoded, firstloop); |
| | 4402 | if (decoded <= 0) |
| | 4403 | break; |
| | 4404 | |
| | 4405 | total_decoded_audio += decoded; |
| | 4406 | allowedquit |= ringBuffer->InDVDMenuOrStillFrame(); |
| | 4407 | // top off audio buffers initially in audio only mode |
| | 4408 | if (!allowedquit && !wantvideo) |
| | 4409 | allowedquit = TopUpAudioBuffer(decoded, |
| | 4410 | total_decoded_audio, |
| | 4411 | ofill, othresh); |
| | 4412 | break; |
| | 4413 | case CODEC_TYPE_VIDEO: |
| | 4414 | { |
| | 4415 | ret = ProcessVideoPacket(pkt, stream, pts, firstloop); |
| | 4416 | break; |
| | 4417 | } |
| | 4418 | case CODEC_TYPE_SUBTITLE: |
| | 4419 | { |
| | 4420 | ret = ProcessSubtitlePacket(pkt, stream, pts); |
| | 4421 | break; |
| | 4422 | } |
| | 4423 | default: |
| | 4424 | { |
| | 4425 | VERBOSE(VB_IMPORTANT, LOC_ERR + |
| | 4426 | QString("Decoding - id(%1) type(%2)") |
| | 4427 | .arg(codec_id_string(ctx->codec_id)) |
| | 4428 | .arg(codec_type_string(ctx->codec_type))); |
| | 4429 | ret = len; |
| | 4430 | break; |
| | 4431 | } |
| | 4432 | } |
| | 4433 | ptr += ret; |
| | 4434 | len -= ret; |
| | 4435 | firstloop = false; |
| | 4436 | } |
| | 4437 | av_free_packet(pkt); |
| | 4438 | } |
| | 4439 | |
| | 4440 | if (pkt) |
| | 4441 | delete pkt; |
| | 4442 | |
| | 4443 | return true; |
| | 4444 | } |
| | 4445 | |
| | 4446 | bool AvFormatDecoder::UpdateDVDStatus() |
| | 4447 | { |
| | 4448 | int dvdtitle = 0; |
| | 4449 | int dvdpart = 0; |
| | 4450 | bool cellChanged = ringBuffer->DVD()->CellChanged(); |
| | 4451 | bool inDVDStill = ringBuffer->DVD()->InStillFrame(); |
| | 4452 | bool inDVDMenu = ringBuffer->DVD()->IsInMenu(); |
| | 4453 | int storedPktCount = storedPackets.count(); |
| | 4454 | bool storevideoframes = false; |
| | 4455 | selectedVideoIndex = 0; |
| | 4456 | |
| | 4457 | ringBuffer->DVD()->GetPartAndTitle(dvdpart, dvdtitle); |
| | 4458 | |
| | 4459 | if (dvdTitleChanged) |
| | 4460 | { |
| | 4461 | if ((storedPktCount > 10 && !decodeStillFrame) || decodeStillFrame) |
| | 4462 | { |
| | 4463 | storevideoframes = dvdTitleChanged = false; |
| | 4464 | ScanStreams(true); |
| | 4465 | } |
| | 4466 | else |
| | 4467 | storevideoframes = true; |
| | 4468 | } |
| | 4469 | else |
| | 4470 | { |
| | 4471 | storevideoframes = false; |
| | 4472 | |
| | 4473 | if (storedPktCount < 2 && !decodeStillFrame) |
| | 4474 | storevideoframes = true; |
| | 4475 | |
| | 4476 | VERBOSE(VB_PLAYBACK+VB_EXTRA, QString("DVD Playback Debugging " |
| | 4477 | "inDVDMenu %1 storedPacketcount %2 dvdstill %3") |
| | 4478 | .arg(inDVDMenu).arg(storedPktCount).arg(inDVDStill)); |
| | 4479 | |
| | 4480 | if (inDVDStill && storedPktCount == 0 && |
| | 4481 | GetNVP()->getVideoOutput()->ValidVideoFrames() == 0) |
| | 4482 | { |
| | 4483 | ringBuffer->DVD()->RunSeekCellStart(); |
| | 4484 | } |
| | 4485 | } |
| | 4486 | |
| | 4487 | if (GetNVP()->AtNormalSpeed() && (cellChanged || lastdvdtitle != dvdtitle)) |
| | 4488 | { |
| | 4489 | if (dvdtitle != lastdvdtitle) |
| | 4490 | { |
| | 4491 | VERBOSE(VB_PLAYBACK, LOC + "DVD Title Changed"); |
| | 4492 | lastdvdtitle = dvdtitle; |
| | 4493 | if (lastdvdtitle != -1) |
| | 4494 | dvdTitleChanged = true; |
| | 4495 | if (GetNVP() && GetNVP()->getVideoOutput()) |
| | 4496 | { |
| | 4497 | if (ringBuffer->DVD()->InStillFrame()) |
| | 4498 | GetNVP()->getVideoOutput()->SetPrebuffering(false); |
| | 4499 | else |
| | 4500 | GetNVP()->getVideoOutput()->SetPrebuffering(true); |
| | 4501 | } |
| | 4502 | } |
| | 4503 | |
| | 4504 | if (ringBuffer->DVD()->PGCLengthChanged()) |
| | 4505 | { |
| | 4506 | { |
| | 4507 | QMutexLocker locker(&m_positionMapLock); |
| | 4508 | posmapStarted = false; |
| | 4509 | m_positionMap.clear(); |
| | 4510 | } |
| | 4511 | SyncPositionMap(); |
| | 4512 | } |
| | 4513 | |
| | 4514 | UpdateDVDFramesPlayed(); |
| | 4515 | VERBOSE(VB_PLAYBACK, QString(LOC + "DVD Cell Changed. " |
| | 4516 | "Update framesPlayed: %1") |
| | 4517 | .arg(framesPlayed)); |
| | 4518 | } |
| | 4519 | |
| | 4520 | return storevideoframes; |
| | 4521 | } |
| | 4522 | |
| | 4523 | bool AvFormatDecoder::PreProcessDVDVideoPacket(AVPacket *pkt, AVStream *stream) |
| | 4524 | { |
| | 4525 | |
| | 4526 | MpegPreProcessPkt(stream, pkt); |
| 4026 | | if (len > 0 && |
| 4027 | | curstream->codec->codec_type == CODEC_TYPE_DATA && |
| 4028 | | curstream->codec->codec_id == CODEC_ID_MPEG2VBI) |
| 4029 | | { |
| 4030 | | ProcessVBIDataPacket(curstream, pkt); |
| 4031 | | |
| 4032 | | av_free_packet(pkt); |
| 4033 | | continue; |
| 4034 | | } |
| 4035 | | |
| 4036 | | if (len > 0 && |
| 4037 | | ((curstream->codec->codec_type == CODEC_TYPE_DATA && |
| 4038 | | curstream->codec->codec_id == CODEC_ID_DVB_VBI) || |
| 4039 | | (curstream->codec->codec_type == CODEC_TYPE_SUBTITLE && |
| 4040 | | curstream->codec->codec_id == CODEC_ID_DVB_TELETEXT))) |
| 4041 | | { |
| 4042 | | ProcessDVBDataPacket(curstream, pkt); |
| 4043 | | |
| 4044 | | av_free_packet(pkt); |
| 4045 | | continue; |
| 4046 | | } |
| 4047 | | |
| 4048 | | #ifdef USING_MHEG |
| 4049 | | if (len > 0 && |
| 4050 | | curstream->codec->codec_type == CODEC_TYPE_DATA && |
| 4051 | | curstream->codec->codec_id == CODEC_ID_DSMCC_B) |
| 4052 | | { |
| 4053 | | ProcessDSMCCPacket(curstream, pkt); |
| 4054 | | |
| 4055 | | av_free_packet(pkt); |
| 4056 | | |
| 4057 | | // Have to return regularly to ensure that the OSD is updated. |
| 4058 | | // This applies both to MHEG and also channel browsing. |
| 4059 | | if (!(decodetype & kDecodeVideo)) |
| 4060 | | { |
| 4061 | | allowedquit |= (itv && itv->ImageHasChanged()); |
| 4062 | | OSD *osd = NULL; |
| 4063 | | if (!allowedquit && GetNVP() && (osd = GetNVP()->GetOSD())) |
| 4064 | | allowedquit |= osd->HasChanged(); |
| 4065 | | } |
| 4066 | | |
| 4067 | | continue; |
| 4068 | | } |
| 4069 | | #endif // USING_MHEG |
| 4070 | | |
| 4071 | | // we don't care about other data streams |
| 4072 | | if (curstream->codec->codec_type == CODEC_TYPE_DATA) |
| 4073 | | { |
| 4074 | | av_free_packet(pkt); |
| 4075 | | continue; |
| 4076 | | } |
| 4077 | | |
| 4078 | | if (!curstream->codec->codec) |
| 4079 | | { |
| 4080 | | VERBOSE(VB_PLAYBACK, LOC + |
| 4081 | | QString("No codec for stream index %1, type(%2) id(%3:%4)") |
| 4082 | | .arg(pkt->stream_index) |
| 4083 | | .arg(codec_type_string(curstream->codec->codec_type)) |
| 4084 | | .arg(codec_id_string(curstream->codec->codec_id)) |
| 4085 | | .arg(curstream->codec->codec_id)); |
| 4086 | | av_free_packet(pkt); |
| 4087 | | continue; |
| 4088 | | } |
| 4089 | | |
| 4090 | | firstloop = true; |
| 4091 | | have_err = false; |
| 4092 | | |
| 4093 | | avcodeclock->lock(); |
| 4094 | | int ctype = curstream->codec->codec_type; |
| 4095 | | int audIdx = selectedTrack[kTrackTypeAudio].av_stream_index; |
| 4096 | | int audSubIdx = selectedTrack[kTrackTypeAudio].av_substream_index; |
| 4097 | | int subIdx = selectedTrack[kTrackTypeSubtitle].av_stream_index; |
| 4098 | | avcodeclock->unlock(); |
| 4099 | | |
| 4100 | | while (!have_err && len > 0) |
| 4101 | | { |
| 4102 | | int ret = 0; |
| 4103 | | bool dts = false; |
| 4104 | | switch (ctype) |
| 4105 | | { |
| 4106 | | case CODEC_TYPE_AUDIO: |
| 4107 | | { |
| 4108 | | bool reselectAudioTrack = false; |
| 4109 | | char *s; |
| 4110 | | |
| 4111 | | /// HACK HACK HACK -- begin See #3731 |
| 4112 | | if (!GetNVP()->HasAudioIn()) |
| 4113 | | { |
| 4114 | | VERBOSE(VB_AUDIO, LOC + "Audio is disabled - trying to restart it"); |
| 4115 | | reselectAudioTrack = true; |
| 4116 | | } |
| 4117 | | /// HACK HACK HACK -- end |
| 4118 | | |
| 4119 | | // detect switches between stereo and dual languages |
| 4120 | | bool wasDual = audSubIdx != -1; |
| 4121 | | bool isDual = curstream->codec->avcodec_dual_language; |
| 4122 | | if ((wasDual && !isDual) || (!wasDual && isDual)) |
| 4123 | | { |
| 4124 | | SetupAudioStreamSubIndexes(audIdx); |
| 4125 | | reselectAudioTrack = true; |
| 4126 | | } |
| 4127 | | |
| 4128 | | // detect channels on streams that need |
| 4129 | | // to be decoded before we can know this |
| 4130 | | bool already_decoded = false; |
| 4131 | | if (!curstream->codec->channels) |
| 4132 | | { |
| 4133 | | QMutexLocker locker(avcodeclock); |
| 4134 | | VERBOSE(VB_IMPORTANT, LOC + |
| 4135 | | QString("Setting channels to %1") |
| 4136 | | .arg(audioOut.channels)); |
| 4137 | | |
| 4138 | | if (DoPassThrough(curstream->codec)) |
| 4139 | | { |
| 4140 | | // for passthru let it select the max number |
| 4141 | | // of channels |
| 4142 | | curstream->codec->channels = 0; |
| 4143 | | curstream->codec->request_channels = 0; |
| 4144 | | } |
| 4145 | | else |
| 4146 | | { |
| 4147 | | curstream->codec->channels = audioOut.channels; |
| 4148 | | curstream->codec->request_channels = |
| 4149 | | audioOut.channels; |
| 4150 | | } |
| 4151 | | data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
| 4152 | | ret = avcodec_decode_audio2(curstream->codec, |
| 4153 | | audioSamples, &data_size, |
| 4154 | | ptr, len); |
| 4155 | | already_decoded = true; |
| 4156 | | |
| 4157 | | reselectAudioTrack |= curstream->codec->channels; |
| 4158 | | } |
| 4159 | | |
| 4160 | | if (curstream->codec->codec_id == CODEC_ID_AC3) |
| 4161 | | { |
| 4162 | | GetBitContext gbc; |
| 4163 | | init_get_bits(&gbc, ptr, len * 8); |
| 4164 | | if (!ff_ac3_parse_header(&gbc, &hdr)) |
| 4165 | | { |
| 4166 | | if (hdr.channels != last_ac3_channels) |
| 4167 | | { |
| 4168 | | VERBOSE(VB_AUDIO, LOC + QString("AC3 changed from %1 to %2 channels (frame %3)") |
| 4169 | | .arg(last_ac3_channels).arg(hdr.channels).arg(framesRead)); |
| 4170 | | if ((framesRead - last_framesRead) > AUDIOMAXFRAMES || |
| 4171 | | hdr.channels < last_ac3_channels) |
| 4172 | | curstream->codec->channels = hdr.channels; |
| 4173 | | last_ac3_channels = hdr.channels; |
| 4174 | | last_framesRead = framesRead; |
| 4175 | | SetupAudioStream(); |
| 4176 | | } |
| 4177 | | } |
| 4178 | | } |
| 4179 | | |
| 4180 | | if (reselectAudioTrack) |
| 4181 | | { |
| 4182 | | QMutexLocker locker(avcodeclock); |
| 4183 | | currentTrack[kTrackTypeAudio] = -1; |
| 4184 | | selectedTrack[kTrackTypeAudio] |
| 4185 | | .av_stream_index = -1; |
| 4186 | | audIdx = -1; |
| 4187 | | audSubIdx = -1; |
| 4188 | | AutoSelectAudioTrack(); |
| 4189 | | audIdx = selectedTrack[kTrackTypeAudio] |
| 4190 | | .av_stream_index; |
| 4191 | | audSubIdx = selectedTrack[kTrackTypeAudio] |
| 4192 | | .av_substream_index; |
| 4193 | | } |
| 4194 | | |
| 4195 | | if (!(decodetype & kDecodeAudio) || |
| 4196 | | (pkt->stream_index != audIdx)) |
| 4197 | | { |
| 4198 | | ptr += len; |
| 4199 | | len = 0; |
| 4200 | | continue; |
| 4201 | | } |
| 4202 | | |
| 4203 | | if (firstloop && pkt->pts != (int64_t)AV_NOPTS_VALUE) |
| 4204 | | lastapts = (long long)(av_q2d(curstream->time_base) * |
| 4205 | | pkt->pts * 1000); |
| 4206 | | |
| 4207 | | if (skipaudio) |
| 4208 | | { |
| 4209 | | if ((lastapts < lastvpts - (10.0 / fps)) || |
| 4210 | | lastvpts == 0) |
| 4211 | | { |
| 4212 | | ptr += len; |
| 4213 | | len = 0; |
| 4214 | | continue; |
| 4215 | | } |
| 4216 | | else |
| 4217 | | skipaudio = false; |
| 4218 | | } |
| 4219 | | |
| 4220 | | avcodeclock->lock(); |
| 4221 | | data_size = 0; |
| 4222 | | |
| 4223 | | if (audioOut.do_passthru) |
| 4224 | | { |
| 4225 | | data_size = pkt->size; |
| 4226 | | dts = CODEC_ID_DTS == curstream->codec->codec_id; |
| 4227 | | ret = encode_frame(dts, ptr, len, |
| 4228 | | audioSamples, data_size); |
| 4229 | | s = (char *)audioSamples; |
| 4230 | | } |
| 4231 | | else |
| 4232 | | { |
| 4233 | | AVCodecContext *ctx = curstream->codec; |
| 4234 | | |
| 4235 | | if ((ctx->channels == 0) || |
| 4236 | | (ctx->channels > audioOut.channels)) |
| 4237 | | { |
| 4238 | | ctx->channels = audioOut.channels; |
| 4239 | | } |
| 4240 | | |
| 4241 | | if (!already_decoded) |
| 4242 | | { |
| 4243 | | curstream->codec->request_channels = |
| 4244 | | audioOut.channels; |
| 4245 | | data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
| 4246 | | ret = avcodec_decode_audio2(ctx, audioSamples, |
| 4247 | | &data_size, ptr, len); |
| 4248 | | } |
| 4249 | | |
| 4250 | | // Convert sample format if required (Myth only handles 8 and 16 bits audio) |
| 4251 | | if (ctx->sample_fmt != SAMPLE_FMT_S16 && ctx->sample_fmt != SAMPLE_FMT_U8) |
| 4252 | | { |
| 4253 | | if (audio_src_fmt != ctx->sample_fmt) |
| 4254 | | { |
| 4255 | | if (reformat_ctx) |
| 4256 | | av_audio_convert_free(reformat_ctx); |
| 4257 | | reformat_ctx = av_audio_convert_alloc(SAMPLE_FMT_S16, 1, |
| 4258 | | ctx->sample_fmt, 1, |
| 4259 | | NULL, 0); |
| 4260 | | if (!reformat_ctx || |
| 4261 | | (!audioSamplesResampled && |
| 4262 | | !(audioSamplesResampled = (short int *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE * |
| 4263 | | sizeof(*audioSamplesResampled))))) |
| 4264 | | { |
| 4265 | | VERBOSE(VB_PLAYBACK, QString("Cannot convert %1 sample format to %2 sample format") |
| 4266 | | .arg(avcodec_get_sample_fmt_name(ctx->sample_fmt)) |
| 4267 | | .arg(avcodec_get_sample_fmt_name(SAMPLE_FMT_S16))); |
| 4268 | | |
| 4269 | | avcodeclock->unlock(); |
| 4270 | | have_err = true; |
| 4271 | | continue; |
| 4272 | | } |
| 4273 | | audio_src_fmt = ctx->sample_fmt; |
| 4274 | | } |
| 4275 | | } |
| 4276 | | |
| 4277 | | if (reformat_ctx) |
| 4278 | | { |
| 4279 | | const void *ibuf[6] = {audioSamples}; |
| 4280 | | void *obuf[6] = {audioSamplesResampled}; |
| 4281 | | int istride[6] = {av_get_bits_per_sample_format(ctx->sample_fmt)/8}; |
| 4282 | | int ostride[6] = {2}; |
| 4283 | | int len = data_size/istride[0]; |
| 4284 | | if (av_audio_convert(reformat_ctx, obuf, ostride, |
| 4285 | | ibuf, istride, len) < 0) |
| 4286 | | { |
| 4287 | | VERBOSE(VB_PLAYBACK, "av_audio_convert() failed"); |
| 4288 | | |
| 4289 | | avcodeclock->unlock(); |
| 4290 | | have_err = true; |
| 4291 | | continue; |
| 4292 | | } |
| 4293 | | |
| 4294 | | data_size = len * 2; |
| 4295 | | s = (char *)audioSamplesResampled; |
| 4296 | | } |
| 4297 | | else |
| 4298 | | s = (char *)audioSamples; |
| 4299 | | |
| 4300 | | // When decoding some audio streams the number of |
| 4301 | | // channels, etc isn't known until we try decoding it. |
| 4302 | | if ((ctx->sample_rate != audioOut.sample_rate) || |
| 4303 | | (ctx->channels != audioOut.channels)) |
| 4304 | | { |
| 4305 | | VERBOSE(VB_IMPORTANT, "audio stream changed"); |
| 4306 | | currentTrack[kTrackTypeAudio] = -1; |
| 4307 | | selectedTrack[kTrackTypeAudio] |
| 4308 | | .av_stream_index = -1; |
| 4309 | | audIdx = -1; |
| 4310 | | AutoSelectAudioTrack(); |
| 4311 | | data_size = 0; |
| 4312 | | } |
| 4313 | | } |
| 4314 | | avcodeclock->unlock(); |
| 4315 | | |
| 4316 | | if (ret < 0) |
| 4317 | | { |
| 4318 | | if (!dts) |
| 4319 | | { |
| 4320 | | VERBOSE(VB_IMPORTANT, LOC_ERR + |
| 4321 | | "Unknown audio decoding error"); |
| 4322 | | } |
| 4323 | | have_err = true; |
| 4324 | | continue; |
| 4325 | | } |
| 4326 | | |
| 4327 | | if (data_size <= 0) |
| 4328 | | { |
| 4329 | | ptr += ret; |
| 4330 | | len -= ret; |
| 4331 | | continue; |
| 4332 | | } |
| 4333 | | |
| 4334 | | long long temppts = lastapts; |
| 4335 | | |
| 4336 | | // calc for next frame |
| 4337 | | lastapts += (long long)((double)(data_size * 1000) / |
| 4338 | | (curstream->codec->channels * 2) / |
| 4339 | | curstream->codec->sample_rate); |
| 4340 | | |
| 4341 | | VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, |
| 4342 | | LOC + QString("audio timecode %1 %2 %3 %4") |
| 4343 | | .arg(pkt->pts).arg(pkt->dts) |
| 4344 | | .arg(temppts).arg(lastapts)); |
| 4345 | | |
| 4346 | | if (audSubIdx != -1) |
| 4347 | | { |
| 4348 | | extract_mono_channel(audSubIdx, &audioOut, |
| 4349 | | s, data_size); |
| 4350 | | } |
| 4351 | | |
| 4352 | | GetNVP()->AddAudioData(s, data_size, temppts); |
| 4353 | | |
| 4354 | | total_decoded_audio += data_size; |
| 4355 | | |
| 4356 | | allowedquit |= ringBuffer->InDVDMenuOrStillFrame(); |
| 4357 | | allowedquit |= !(decodetype & kDecodeVideo) && |
| 4358 | | (ofill + total_decoded_audio > othresh); |
| 4359 | | |
| 4360 | | // top off audio buffers initially in audio only mode |
| 4361 | | if (!allowedquit && !(decodetype & kDecodeVideo)) |
| 4362 | | { |
| 4363 | | uint fill, total; |
| 4364 | | if (GetNVP()->GetAudioBufferStatus(fill, total)) |
| 4365 | | { |
| 4366 | | total /= 6; // HACK needed for some audio files |
| 4367 | | allowedquit = |
| 4368 | | (fill == 0) || (fill > (total>>1)) || |
| 4369 | | ((total - fill) < (uint) data_size) || |
| 4370 | | (ofill + total_decoded_audio > (total>>2)) || |
| 4371 | | ((total - fill) < (uint) data_size * 2); |
| 4372 | | } |
| 4373 | | else |
| 4374 | | { |
| 4375 | | VERBOSE(VB_IMPORTANT, LOC_ERR + |
| 4376 | | "GetFrame() : Failed to top off " |
| 4377 | | "buffers in audio only mode"); |
| 4378 | | } |
| 4379 | | } |
| 4380 | | |
| 4381 | | break; |
| 4382 | | } |
| 4383 | | case CODEC_TYPE_VIDEO: |
| 4384 | | { |
| 4385 | | if (pkt->stream_index != selectedVideoIndex) |
| 4386 | | { |
| 4387 | | ptr += pkt->size; |
| 4388 | | len -= pkt->size; |
| 4389 | | continue; |
| 4390 | | } |
| 4391 | | |
| 4392 | | if (firstloop && pts != (int64_t) AV_NOPTS_VALUE) |
| 4393 | | { |
| 4394 | | lastccptsu = (long long) |
| 4395 | | (av_q2d(curstream->time_base)*pkt->pts*1000000); |
| 4396 | | } |
| 4397 | | |
| 4398 | | if (!(decodetype & kDecodeVideo)) |
| 4399 | | { |
| 4400 | | framesPlayed++; |
| 4401 | | gotvideo = 1; |
| 4402 | | ptr += pkt->size; |
| 4403 | | len -= pkt->size; |
| 4404 | | continue; |
| 4405 | | } |
| 4406 | | |
| 4407 | | AVCodecContext *context = curstream->codec; |
| 4408 | | AVFrame mpa_pic; |
| 4409 | | bzero(&mpa_pic, sizeof(AVFrame)); |
| 4410 | | |
| 4411 | | int gotpicture = 0; |
| 4412 | | |
| 4413 | | avcodeclock->lock(); |
| 4414 | | if (d->HasDecoder()) |
| 4415 | | { |
| 4416 | | if (decodeStillFrame) |
| 4417 | | { |
| 4418 | | int count = 0; |
| 4419 | | // HACK |
| 4420 | | while (!gotpicture && count < 5) |
| 4421 | | { |
| 4422 | | ret = d->DecodeMPEG2Video(context, &mpa_pic, |
| 4423 | | &gotpicture, ptr, len); |
| 4424 | | count++; |
| 4425 | | } |
| 4426 | | } |
| 4427 | | else |
| 4428 | | { |
| 4429 | | ret = d->DecodeMPEG2Video(context, &mpa_pic, |
| 4430 | | &gotpicture, ptr, len); |
| 4431 | | } |
| 4432 | | } |
| 4433 | | else |
| 4434 | | { |
| 4435 | | ret = avcodec_decode_video(context, &mpa_pic, |
| 4436 | | &gotpicture, ptr, len); |
| 4437 | | // Reparse it to not drop the DVD still frame |
| 4438 | | if (decodeStillFrame) |
| 4439 | | ret = avcodec_decode_video(context, &mpa_pic, |
| 4440 | | &gotpicture, ptr, len); |
| 4441 | | } |
| 4442 | | avcodeclock->unlock(); |
| 4443 | | |
| 4444 | | if (ret < 0) |
| 4445 | | { |
| 4446 | | VERBOSE(VB_IMPORTANT, LOC_ERR + |
| 4447 | | "Unknown decoding error"); |
| 4448 | | have_err = true; |
| 4449 | | continue; |
| 4450 | | } |
| 4451 | | |
| 4452 | | if (!gotpicture) |
| 4453 | | { |
| 4454 | | ptr += ret; |
| 4455 | | len -= ret; |
| 4456 | | continue; |
| 4457 | | } |
| 4458 | | |
| 4459 | | // Decode CEA-608 and CEA-708 captions |
| 4460 | | for (uint i = 0; i < (uint)mpa_pic.atsc_cc_len; |
| 4461 | | i += ((mpa_pic.atsc_cc_buf[i] & 0x1f) * 3) + 2) |
| 4462 | | { |
| 4463 | | DecodeDTVCC(mpa_pic.atsc_cc_buf + i, |
| 4464 | | mpa_pic.atsc_cc_len - i); |
| 4465 | | } |
| 4466 | | |
| 4467 | | VideoFrame *picframe = (VideoFrame *)(mpa_pic.opaque); |
| 4468 | | |
| 4469 | | if (!directrendering) |
| 4470 | | { |
| 4471 | | AVPicture tmppicture; |
| 4472 | | |
| 4473 | | VideoFrame *xf = picframe; |
| 4474 | | picframe = GetNVP()->GetNextVideoFrame(false); |
| 4475 | | |
| 4476 | | unsigned char *buf = picframe->buf; |
| 4477 | | avpicture_fill(&tmppicture, buf, PIX_FMT_YUV420P, |
| 4478 | | context->width, context->height); |
| 4479 | | tmppicture.data[0] = buf + picframe->offsets[0]; |
| 4480 | | tmppicture.data[1] = buf + picframe->offsets[1]; |
| 4481 | | tmppicture.data[2] = buf + picframe->offsets[2]; |
| 4482 | | tmppicture.linesize[0] = picframe->pitches[0]; |
| 4483 | | tmppicture.linesize[1] = picframe->pitches[1]; |
| 4484 | | tmppicture.linesize[2] = picframe->pitches[2]; |
| 4485 | | |
| 4486 | | sws_ctx = sws_getCachedContext(sws_ctx, context->width, |
| 4487 | | context->height, context->pix_fmt, |
| 4488 | | context->width, context->height, |
| 4489 | | PIX_FMT_YUV420P, SWS_FAST_BILINEAR, |
| 4490 | | NULL, NULL, NULL); |
| 4491 | | if (!sws_ctx) |
| 4492 | | { |
| 4493 | | VERBOSE(VB_IMPORTANT, LOC_ERR + |
| 4494 | | "Failed to allocate sws context"); |
| 4495 | | have_err = true; |
| 4496 | | continue; |
| 4497 | | } |
| 4498 | | sws_scale(sws_ctx, mpa_pic.data, mpa_pic.linesize, |
| 4499 | | 0, context->height, tmppicture.data, |
| 4500 | | tmppicture.linesize); |
| 4501 | | |
| 4502 | | |
| 4503 | | if (xf) |
| 4504 | | { |
| 4505 | | // Set the frame flags, but then discard it |
| 4506 | | // since we are not using it for display. |
| 4507 | | xf->interlaced_frame = mpa_pic.interlaced_frame; |
| 4508 | | xf->top_field_first = mpa_pic.top_field_first; |
| 4509 | | xf->frameNumber = framesPlayed; |
| 4510 | | GetNVP()->DiscardVideoFrame(xf); |
| 4511 | | } |
| 4512 | | } |
| 4513 | | |
| 4514 | | long long temppts = pts; |
| 4515 | | |
| 4516 | | // Validate the video pts against the last pts. If it's |
| 4517 | | // a little bit smaller, equal or not available, compute |
| 4518 | | // it from the last. Otherwise assume a wraparound. |
| 4519 | | if (!ringBuffer->isDVD() && |
| 4520 | | temppts <= lastvpts && |
| 4521 | | (temppts + 10000 > lastvpts || temppts <= 0)) |
| 4522 | | { |
| 4523 | | temppts = lastvpts; |
| 4524 | | temppts += (long long)(1000 / fps); |
| 4525 | | // MPEG2/H264 frames can be repeated, update pts accordingly |
| 4526 | | temppts += (long long)(mpa_pic.repeat_pict * 500 / fps); |
| 4527 | | } |
| 4528 | | |
| 4529 | | VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + |
| 4530 | | QString("video timecode %1 %2 %3 %4") |
| 4531 | | .arg(pkt->pts).arg(pkt->dts).arg(temppts) |
| 4532 | | .arg(lastvpts)); |
| 4533 | | |
| 4534 | | /* XXX: Broken. |
| 4535 | | if (mpa_pic.qscale_table != NULL && mpa_pic.qstride > 0 && |
| 4536 | | context->height == picframe->height) |
| 4537 | | { |
| 4538 | | int tblsize = mpa_pic.qstride * |
| 4539 | | ((picframe->height + 15) / 16); |
| 4540 | | |
| 4541 | | if (picframe->qstride != mpa_pic.qstride || |
| 4542 | | picframe->qscale_table == NULL) |
| 4543 | | { |
| 4544 | | picframe->qstride = mpa_pic.qstride; |
| 4545 | | if (picframe->qscale_table) |
| 4546 | | delete [] picframe->qscale_table; |
| 4547 | | picframe->qscale_table = new unsigned char[tblsize]; |
| 4548 | | } |
| 4549 | | |
| 4550 | | memcpy(picframe->qscale_table, mpa_pic.qscale_table, |
| 4551 | | tblsize); |
| 4552 | | } |
| 4553 | | */ |
| 4554 | | |
| 4555 | | picframe->interlaced_frame = mpa_pic.interlaced_frame; |
| 4556 | | picframe->top_field_first = mpa_pic.top_field_first; |
| 4557 | | picframe->repeat_pict = mpa_pic.repeat_pict; |
| 4558 | | |
| 4559 | | picframe->frameNumber = framesPlayed; |
| 4560 | | GetNVP()->ReleaseNextVideoFrame(picframe, temppts); |
| 4561 | | if (d->HasMPEG2Dec() && mpa_pic.data[3]) |
| 4562 | | context->release_buffer(context, &mpa_pic); |
| 4563 | | |
| 4564 | | decoded_video_frame = picframe; |
| 4565 | | gotvideo = 1; |
| 4566 | | framesPlayed++; |
| 4567 | | |
| 4568 | | lastvpts = temppts; |
| 4569 | | break; |
| 4570 | | } |
| 4571 | | case CODEC_TYPE_SUBTITLE: |
| 4572 | | { |
| 4573 | | int gotSubtitles = 0; |
| 4574 | | AVSubtitle subtitle; |
| 4575 | | memset(&subtitle, 0, sizeof(AVSubtitle)); |
| 4576 | | |
| 4577 | | if (ringBuffer->isDVD()) |
| 4578 | | { |
| 4579 | | if (ringBuffer->DVD()->NumMenuButtons() > 0) |
| 4580 | | { |
| 4581 | | ringBuffer->DVD()->GetMenuSPUPkt(ptr, len, |
| 4582 | | curstream->id); |
| 4583 | | } |
| 4584 | | else |
| 4585 | | { |
| 4586 | | if (pkt->stream_index == subIdx) |
| 4587 | | { |
| 4588 | | QMutexLocker locker(avcodeclock); |
| 4589 | | ringBuffer->DVD()->DecodeSubtitles(&subtitle, |
| 4590 | | &gotSubtitles, |
| 4591 | | ptr, len); |
| 4592 | | } |
| 4593 | | } |
| 4594 | | } |
| 4595 | | else if (pkt->stream_index == subIdx) |
| 4596 | | { |
| 4597 | | QMutexLocker locker(avcodeclock); |
| 4598 | | avcodec_decode_subtitle(curstream->codec, |
| 4599 | | &subtitle, &gotSubtitles, |
| 4600 | | ptr, len); |
| 4601 | | } |
| 4602 | | |
| 4603 | | // the subtitle decoder always consumes the whole packet |
| 4604 | | ptr += len; |
| 4605 | | len = 0; |
| 4606 | | |
| 4607 | | if (gotSubtitles) |
| 4608 | | { |
| 4609 | | subtitle.start_display_time += pts; |
| 4610 | | subtitle.end_display_time += pts; |
| 4611 | | GetNVP()->AddAVSubtitle(subtitle); |
| 4612 | | |
| 4613 | | VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + |
| 4614 | | QString("subtl timecode %1 %2 %3 %4") |
| 4615 | | .arg(pkt->pts).arg(pkt->dts) |
| 4616 | | .arg(subtitle.start_display_time) |
| 4617 | | .arg(subtitle.end_display_time)); |
| 4618 | | } |
| 4619 | | |
| 4620 | | break; |
| 4621 | | } |
| 4622 | | default: |
| 4623 | | { |
| 4624 | | AVCodecContext *enc = curstream->codec; |
| 4625 | | VERBOSE(VB_IMPORTANT, LOC_ERR + |
| 4626 | | QString("Decoding - id(%1) type(%2)") |
| 4627 | | .arg(codec_id_string(enc->codec_id)) |
| 4628 | | .arg(codec_type_string(enc->codec_type))); |
| 4629 | | have_err = true; |
| 4630 | | break; |
| 4631 | | } |
| 4632 | | } |
| 4633 | | |
| 4634 | | if (!have_err) |
| 4635 | | { |
| 4636 | | ptr += ret; |
| 4637 | | len -= ret; |
| 4638 | | frame_decoded = 1; |
| 4639 | | firstloop = false; |
| 4640 | | } |
| 4641 | | } |
| 4642 | | |
| 4643 | | av_free_packet(pkt); |
| 4644 | | } |
| 4645 | | |
| 4646 | | if (pkt) |
| 4647 | | delete pkt; |
| 4648 | | |