bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.4k stars 1.57k forks source link

javacv1.5.3 has no way to convert h265 encoding to h264 #2142

Closed lianyf1994 closed 6 months ago

lianyf1994 commented 6 months ago

In the use of javacv1.5.3 version for video code flow code push encountered some problems, maven relies on the following, when the video encoding is h265, the stream in h264 encoding flv format pushed to the streaming media server, there will be the following errors

org.bytedeco javacv 1.5.3
    <dependency>
        <groupId>org.bytedeco</groupId>
        <artifactId>ffmpeg-platform</artifactId>
        <version>4.2.2-1.5.3</version>
    </dependency>

    org.bytedeco.javacv.FrameRecorder$Exception: avformat_write_header error() error -40: Could not write header to 'null'
at org.bytedeco.javacv.FFmpegFrameRecorder.startUnsafe(FFmpegFrameRecorder.java:952)
at org.bytedeco.javacv.FFmpegFrameRecorder.start(FFmpegFrameRecorder.java:431)
at org.bytedeco.javacv.FFmpegFrameRecorder.start(FFmpegFrameRecorder.java:426)
at com.banmajio.push.RtmpPush.push(RtmpPush.java:138)
at com.banmajio.push.RealPlay.play(RealPlay.java:59)
at com.banmajio.controller.HcSDKController.openstream(HcSDKController.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
saudet commented 6 months ago

Please try again with JavaCV 1.5.9

saudet commented 6 months ago

I assume that's working in JavaCV 1.5.9. Please let me know if that's not the case

lianyf1994 commented 6 months ago

Yes, javacv1.5.9 can indeed convert h.265 encoding to h.264, but I have encountered new problems. I want to control the playback speed of the video after transcoding. Some blogs say that pts and dts are recalculated for the video timestamp, I wonder if javacv1.5.9 can do this. If you can give me some references, thank you

saudet commented 6 months ago

We can set the timestamp to whatever we want by calling setTimestamp() before record()

lianyf1994 commented 6 months ago

Any ideas? My code is as follows, how can I modify to achieve double speed playback? avutil.av_log_set_level(avutil.AV_LOG_QUIET); FFmpegLogCallback.set(); grabber = new FFmpegFrameGrabber(inputStream, 0); grabber.setVideoOption("vcodec", "copy"); grabber.setFormat("mpeg"); grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); grabber.setVideoCodec(avcodec.AV_CODEC_ID_H264); grabber.setAudioStream(Integer.MAX_VALUE); grabber.start(); recorder = new FFmpegFrameRecorder(pojo.getRtmp(), grabber.getImageWidth(), grabber.getImageHeight()); recorder.setFormat("flv"); recorder.setInterleaved(true); recorder.setVideoOption("preset", "ultrafast"); recorder.setVideoOption("tune", "zerolatency"); recorder.setVideoOption("crf", "25"); recorder.setSampleRate(grabber.getSampleRate()); recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); recorder.setFrameRate(framerate); recorder.setVideoBitrate(grabber.getVideoBitrate()); recorder.setGopSize(50); if (grabber.getVideoCodec() == avcodec.AV_CODEC_ID_H264) { recorder.start(grabber.getFormatContext()); while ((avPacket = grabber.grabPacket()) != null) { recorder.recordPacket(avPacket); } } else { if (grabber.getAudioChannels() > 0) { recorder.setAudioChannels(grabber.getAudioChannels()); recorder.setAudioBitrate(grabber.getAudioBitrate()); recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); } recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); recorder.setVideoCodecName("libx264"); recorder.start(); while ((frame = grabber.grab()) != null) { recorder.record(frame); } }

saudet commented 6 months ago

I'd just double the frame rate

lianyf1994 commented 6 months ago

OK, how can I change it?

saudet commented 6 months ago

We can easily accomplish this with the ffmpeg program: http://bytedeco.org/javacpp-presets/ffmpeg/apidocs/org/bytedeco/ffmpeg/ffmpeg.html