Mercurial > mplayer.hg
comparison mplayer.c @ 25824:eb338d06c638
Add support for dvdnav still frames playback.
Based on various patches from Otvos Attila
and MPlayer'ized by me.
N.B. Always use -vc ffmpeg12 with dvdnav://
author | ben |
---|---|
date | Sat, 26 Jan 2008 11:51:34 +0000 |
parents | 6aad76cd84d3 |
children | 9463ef1a0e63 |
comparison
equal
deleted
inserted
replaced
25823:60fda6c0c7dc | 25824:eb338d06c638 |
---|---|
571 } | 571 } |
572 | 572 |
573 /// step size of mixer changes | 573 /// step size of mixer changes |
574 int volstep = 3; | 574 int volstep = 3; |
575 | 575 |
576 #ifdef USE_DVDNAV | |
577 static void mp_dvdnav_context_free(MPContext *ctx){ | |
578 if (ctx->nav_smpi) free_mp_image(ctx->nav_smpi); | |
579 ctx->nav_smpi = NULL; | |
580 if (ctx->nav_buffer) free(ctx->nav_buffer); | |
581 ctx->nav_buffer = NULL; | |
582 ctx->nav_start = NULL; | |
583 ctx->nav_in_size = 0; | |
584 } | |
585 #endif | |
586 | |
576 void uninit_player(unsigned int mask){ | 587 void uninit_player(unsigned int mask){ |
577 mask=inited_flags&mask; | 588 mask=inited_flags&mask; |
578 | 589 |
579 mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n*** uninit(0x%X)\n",mask); | 590 mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n*** uninit(0x%X)\n",mask); |
580 | 591 |
620 if(mask&INITED_VO){ | 631 if(mask&INITED_VO){ |
621 inited_flags&=~INITED_VO; | 632 inited_flags&=~INITED_VO; |
622 current_module="uninit_vo"; | 633 current_module="uninit_vo"; |
623 mpctx->video_out->uninit(); | 634 mpctx->video_out->uninit(); |
624 mpctx->video_out=NULL; | 635 mpctx->video_out=NULL; |
636 #ifdef USE_DVDNAV | |
637 mp_dvdnav_context_free(mpctx); | |
638 #endif | |
625 } | 639 } |
626 | 640 |
627 // Must be after libvo uninit, as few vo drivers (svgalib) have tty code. | 641 // Must be after libvo uninit, as few vo drivers (svgalib) have tty code. |
628 if(mask&INITED_GETCH2){ | 642 if(mask&INITED_GETCH2){ |
629 inited_flags&=~INITED_GETCH2; | 643 inited_flags&=~INITED_GETCH2; |
1765 } | 1779 } |
1766 } | 1780 } |
1767 return time_frame; | 1781 return time_frame; |
1768 } | 1782 } |
1769 | 1783 |
1784 #ifdef USE_DVDNAV | |
1785 #ifndef FF_B_TYPE | |
1786 #define FF_B_TYPE 3 | |
1787 #endif | |
1788 /// store decoded video image | |
1789 static mp_image_t * mp_dvdnav_copy_mpi(mp_image_t *to_mpi, | |
1790 mp_image_t *from_mpi) { | |
1791 mp_image_t *mpi; | |
1792 | |
1793 /// Do not store B-frames | |
1794 if (from_mpi->pict_type == FF_B_TYPE) | |
1795 return to_mpi; | |
1796 | |
1797 if (to_mpi && | |
1798 to_mpi->w == from_mpi->w && | |
1799 to_mpi->h == from_mpi->h && | |
1800 to_mpi->imgfmt == from_mpi->imgfmt) | |
1801 mpi = to_mpi; | |
1802 else { | |
1803 if (to_mpi) | |
1804 free_mp_image(to_mpi); | |
1805 if (from_mpi->w == 0 || from_mpi->h == 0) | |
1806 return NULL; | |
1807 mpi = alloc_mpi(from_mpi->w,from_mpi->h,from_mpi->imgfmt); | |
1808 } | |
1809 | |
1810 copy_mpi(mpi,from_mpi); | |
1811 return mpi; | |
1812 } | |
1813 | |
1814 static void mp_dvdnav_reset_stream (MPContext *ctx) { | |
1815 if (ctx->sh_video) { | |
1816 /// clear video pts | |
1817 ctx->d_video->pts = 0.0f; | |
1818 ctx->sh_video->pts = 0.0f; | |
1819 ctx->sh_video->i_pts = 0.0f; | |
1820 ctx->sh_video->last_pts = 0.0f; | |
1821 ctx->sh_video->num_buffered_pts = 0; | |
1822 ctx->sh_video->num_frames = 0; | |
1823 ctx->sh_video->num_frames_decoded = 0; | |
1824 ctx->sh_video->timer = 0.0f; | |
1825 ctx->sh_video->stream_delay = 0.0f; | |
1826 ctx->sh_video->timer = 0; | |
1827 ctx->demuxer->stream_pts = MP_NOPTS_VALUE; | |
1828 } | |
1829 | |
1830 if (ctx->sh_audio) { | |
1831 /// free audio packets and reset | |
1832 ds_free_packs(ctx->d_audio); | |
1833 audio_delay -= ctx->sh_audio->stream_delay; | |
1834 ctx->delay =- audio_delay; | |
1835 ctx->audio_out->reset(); | |
1836 resync_audio_stream(ctx->sh_audio); | |
1837 } | |
1838 | |
1839 if (ctx->d_sub) dvdsub_id = -2; | |
1840 | |
1841 audio_delay = 0.0f; | |
1842 correct_pts = 0; | |
1843 | |
1844 /// clear all EOF related flags | |
1845 ctx->d_video->eof = ctx->d_audio->eof = ctx->stream->eof = 0; | |
1846 } | |
1847 | |
1848 /// Restore last decoded DVDNAV (still frame) | |
1849 static mp_image_t *mp_dvdnav_restore_smpi(int *in_size, | |
1850 unsigned char **start, | |
1851 mp_image_t *decoded_frame) | |
1852 { | |
1853 if (mpctx->stream->type != STREAMTYPE_DVDNAV) | |
1854 return decoded_frame; | |
1855 | |
1856 /// a change occured in dvdnav stream | |
1857 if (mp_dvdnav_cell_has_changed(mpctx->stream,0)) { | |
1858 mp_dvdnav_read_wait(mpctx->stream, 1, 1); | |
1859 mp_dvdnav_context_free(mpctx); | |
1860 mp_dvdnav_reset_stream(mpctx); | |
1861 mp_dvdnav_read_wait(mpctx->stream, 0, 1); | |
1862 mp_dvdnav_cell_has_changed(mpctx->stream,1); | |
1863 } | |
1864 | |
1865 if (*in_size < 0) { | |
1866 float len; | |
1867 | |
1868 /// Display still frame, if any | |
1869 if (mpctx->nav_smpi && !mpctx->nav_buffer) | |
1870 decoded_frame = mpctx->nav_smpi; | |
1871 | |
1872 /// increment video frame : continue playing after still frame | |
1873 len = demuxer_get_time_length(mpctx->demuxer); | |
1874 if (mpctx->sh_video->pts >= len && | |
1875 mpctx->sh_video->pts > 0.0 && len > 0.0) { | |
1876 mp_dvdnav_skip_still(mpctx->stream); | |
1877 mp_dvdnav_skip_wait(mpctx->stream); | |
1878 } | |
1879 mpctx->sh_video->pts += 1 / mpctx->sh_video->fps; | |
1880 | |
1881 if (mpctx->nav_buffer) { | |
1882 *start = mpctx->nav_start; | |
1883 *in_size = mpctx->nav_in_size; | |
1884 if (mpctx->nav_start) | |
1885 memcpy(*start,mpctx->nav_buffer,mpctx->nav_in_size); | |
1886 } | |
1887 } | |
1888 | |
1889 return decoded_frame; | |
1890 } | |
1891 | |
1892 /// Save last decoded DVDNAV (still frame) | |
1893 static void mp_dvdnav_save_smpi(int in_size, | |
1894 unsigned char *start, | |
1895 mp_image_t *decoded_frame) | |
1896 { | |
1897 if (mpctx->stream->type != STREAMTYPE_DVDNAV) | |
1898 return; | |
1899 | |
1900 if (mpctx->nav_buffer) | |
1901 free(mpctx->nav_buffer); | |
1902 | |
1903 mpctx->nav_buffer = malloc(in_size); | |
1904 mpctx->nav_start = start; | |
1905 mpctx->nav_in_size = mpctx->nav_buffer ? in_size : -1; | |
1906 if (mpctx->nav_buffer) | |
1907 memcpy(mpctx->nav_buffer,start,in_size); | |
1908 | |
1909 if (decoded_frame && mpctx->nav_smpi != decoded_frame) | |
1910 mpctx->nav_smpi = mp_dvdnav_copy_mpi(mpctx->nav_smpi,decoded_frame); | |
1911 } | |
1912 #endif /* USE_DVDNAV */ | |
1913 | |
1770 static void adjust_sync_and_print_status(int between_frames, float timing_error) | 1914 static void adjust_sync_and_print_status(int between_frames, float timing_error) |
1771 { | 1915 { |
1772 current_module="av_sync"; | 1916 current_module="av_sync"; |
1773 | 1917 |
1774 if(mpctx->sh_audio){ | 1918 if(mpctx->sh_audio){ |
2077 //-------------------- Decode a frame: ----------------------- | 2221 //-------------------- Decode a frame: ----------------------- |
2078 double frame_time; | 2222 double frame_time; |
2079 *blit_frame = 0; // Don't blit if we hit EOF | 2223 *blit_frame = 0; // Don't blit if we hit EOF |
2080 if (!correct_pts) { | 2224 if (!correct_pts) { |
2081 unsigned char* start=NULL; | 2225 unsigned char* start=NULL; |
2082 void *decoded_frame; | 2226 void *decoded_frame = NULL; |
2083 int drop_frame=0; | 2227 int drop_frame=0; |
2084 int in_size; | 2228 int in_size; |
2085 | 2229 |
2086 current_module = "video_read_frame"; | 2230 current_module = "video_read_frame"; |
2087 frame_time = sh_video->next_frame_time; | 2231 frame_time = sh_video->next_frame_time; |
2088 in_size = video_read_frame(sh_video, &sh_video->next_frame_time, | 2232 in_size = video_read_frame(sh_video, &sh_video->next_frame_time, |
2089 &start, force_fps); | 2233 &start, force_fps); |
2234 #ifdef USE_DVDNAV | |
2235 /// wait, still frame or EOF | |
2236 if (mpctx->stream->type == STREAMTYPE_DVDNAV && in_size < 0) { | |
2237 if (mp_dvdnav_is_eof(mpctx->stream)) return -1; | |
2238 if (mpctx->d_video) mpctx->d_video->eof = 0; | |
2239 if (mpctx->d_audio) mpctx->d_audio->eof = 0; | |
2240 mpctx->stream->eof = 0; | |
2241 } else | |
2242 #endif | |
2090 if (in_size < 0) | 2243 if (in_size < 0) |
2091 return -1; | 2244 return -1; |
2092 if (in_size > max_framesize) | 2245 if (in_size > max_framesize) |
2093 max_framesize = in_size; // stats | 2246 max_framesize = in_size; // stats |
2094 sh_video->timer += frame_time; | 2247 sh_video->timer += frame_time; |
2115 } | 2268 } |
2116 update_subtitles(sh_video, mpctx->d_sub, 0); | 2269 update_subtitles(sh_video, mpctx->d_sub, 0); |
2117 update_teletext(sh_video, mpctx->demuxer, 0); | 2270 update_teletext(sh_video, mpctx->demuxer, 0); |
2118 update_osd_msg(); | 2271 update_osd_msg(); |
2119 current_module = "decode_video"; | 2272 current_module = "decode_video"; |
2273 #ifdef USE_DVDNAV | |
2274 decoded_frame = mp_dvdnav_restore_smpi(&in_size,&start,decoded_frame); | |
2275 /// still frame has been reached, no need to decode | |
2276 if (in_size > 0 && !decoded_frame) | |
2277 #endif | |
2120 decoded_frame = decode_video(sh_video, start, in_size, drop_frame, | 2278 decoded_frame = decode_video(sh_video, start, in_size, drop_frame, |
2121 sh_video->pts); | 2279 sh_video->pts); |
2280 #ifdef USE_DVDNAV | |
2281 /// save back last still frame for future display | |
2282 mp_dvdnav_save_smpi(in_size,start,decoded_frame); | |
2283 #endif | |
2122 current_module = "filter_video"; | 2284 current_module = "filter_video"; |
2123 *blit_frame = (decoded_frame && filter_video(sh_video, decoded_frame, | 2285 *blit_frame = (decoded_frame && filter_video(sh_video, decoded_frame, |
2124 sh_video->pts)); | 2286 sh_video->pts)); |
2125 } | 2287 } |
2126 else { | 2288 else { |
3461 if (end_at.type == END_AT_SIZE) { | 3623 if (end_at.type == END_AT_SIZE) { |
3462 mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_MPEndposNoSizeBased); | 3624 mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_MPEndposNoSizeBased); |
3463 end_at.type = END_AT_NONE; | 3625 end_at.type = END_AT_NONE; |
3464 } | 3626 } |
3465 | 3627 |
3628 #ifdef USE_DVDNAV | |
3629 mp_dvdnav_context_free(mpctx); | |
3630 if (mpctx->stream->type == STREAMTYPE_DVDNAV) { | |
3631 mp_dvdnav_read_wait(mpctx->stream, 0, 1); | |
3632 mp_dvdnav_cell_has_changed(mpctx->stream,1); | |
3633 } | |
3634 #endif | |
3466 | 3635 |
3467 while(!mpctx->eof){ | 3636 while(!mpctx->eof){ |
3468 float aq_sleep_time=0; | 3637 float aq_sleep_time=0; |
3469 if(!mpctx->sh_audio && mpctx->d_audio->sh) { | 3638 if(!mpctx->sh_audio && mpctx->d_audio->sh) { |
3470 mpctx->sh_audio = mpctx->d_audio->sh; | 3639 mpctx->sh_audio = mpctx->d_audio->sh; |