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;