diff mbox

[FFmpeg-devel] avcodec/avpacket: add av_packet_make_writable()

Message ID 20180319154216.7728-1-jamrial@gmail.com
State Accepted
Headers show

Commit Message

James Almer March 19, 2018, 3:42 p.m. UTC
Useful as well to quickly make a packet reference counted when it
isn't already so.

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavcodec/avcodec.h  | 11 +++++++++++
 libavcodec/avpacket.c | 24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

Comments

Paul B Mahol March 19, 2018, 3:45 p.m. UTC | #1
On 3/19/18, James Almer <jamrial@gmail.com> wrote:
> Useful as well to quickly make a packet reference counted when it
> isn't already so.
>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  libavcodec/avcodec.h  | 11 +++++++++++
>  libavcodec/avpacket.c | 24 ++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
>

Will this ever be used?
James Almer March 19, 2018, 4:02 p.m. UTC | #2
On 3/19/2018 12:45 PM, Paul B Mahol wrote:
> On 3/19/18, James Almer <jamrial@gmail.com> wrote:
>> Useful as well to quickly make a packet reference counted when it
>> isn't already so.
>>
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>  libavcodec/avcodec.h  | 11 +++++++++++
>>  libavcodec/avpacket.c | 24 ++++++++++++++++++++++++
>>  2 files changed, 35 insertions(+)
>>
> 
> Will this ever be used?

Probably? It's public API, downstream projects and users decide what
they want to use based on their needs.

And in our tree it can for example be used to simplify the change i made
in a22c6a4796 and e91f0c4f8b, or in bitstream filters to allow changes
to be made directly to the input packet's data.
wm4 March 19, 2018, 4:32 p.m. UTC | #3
On Mon, 19 Mar 2018 12:42:16 -0300
James Almer <jamrial@gmail.com> wrote:

> Useful as well to quickly make a packet reference counted when it
> isn't already so.
> 
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  libavcodec/avcodec.h  | 11 +++++++++++
>  libavcodec/avpacket.c | 24 ++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
> 
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index a8322fb62a..a78017f1fb 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -4518,6 +4518,17 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src);
>   */
>  int av_packet_copy_props(AVPacket *dst, const AVPacket *src);
>  
> +/**
> + * Create a writable reference for the data described by a given packet,
> + * avoiding data copy if possible.
> + *
> + * @param pkt Packet whose data should be made writable.
> + *
> + * @return 0 on success, a negative AVERROR on failure. On failure, the
> + *         packet is unchanged.
> + */
> +int av_packet_make_writable(AVPacket *pkt);
> +
>  /**
>   * Convert valid timing fields (timestamps / durations) in a packet from one
>   * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
> diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
> index fe8113ab76..0693ca6f62 100644
> --- a/libavcodec/avpacket.c
> +++ b/libavcodec/avpacket.c
> @@ -652,6 +652,30 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src)
>      src->size = 0;
>  }
>  
> +int av_packet_make_writable(AVPacket *pkt)
> +{
> +    AVBufferRef *buf = NULL;
> +    int ret;
> +
> +    if (pkt->buf && av_buffer_is_writable(pkt->buf))
> +        return 0;
> +
> +    if (!pkt->data)
> +        return AVERROR(EINVAL);
> +
> +    ret = packet_alloc(&buf, pkt->size);
> +    if (ret < 0)
> +        return ret;
> +    if (pkt->size)
> +        memcpy(buf->data, pkt->data, pkt->size);
> +
> +    av_buffer_unref(&pkt->buf);
> +    pkt->buf  = buf;
> +    pkt->data = buf->data;
> +
> +    return 0;
> +}
> +
>  void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
>  {
>      if (pkt->pts != AV_NOPTS_VALUE)

Why not just call av_buffer_make_writable()? This code seems fine too,
though.
James Almer March 19, 2018, 4:49 p.m. UTC | #4
On 3/19/2018 1:32 PM, wm4 wrote:
> On Mon, 19 Mar 2018 12:42:16 -0300
> James Almer <jamrial@gmail.com> wrote:
> 
>> Useful as well to quickly make a packet reference counted when it
>> isn't already so.
>>
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>  libavcodec/avcodec.h  | 11 +++++++++++
>>  libavcodec/avpacket.c | 24 ++++++++++++++++++++++++
>>  2 files changed, 35 insertions(+)
>>
>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>> index a8322fb62a..a78017f1fb 100644
>> --- a/libavcodec/avcodec.h
>> +++ b/libavcodec/avcodec.h
>> @@ -4518,6 +4518,17 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src);
>>   */
>>  int av_packet_copy_props(AVPacket *dst, const AVPacket *src);
>>  
>> +/**
>> + * Create a writable reference for the data described by a given packet,
>> + * avoiding data copy if possible.
>> + *
>> + * @param pkt Packet whose data should be made writable.
>> + *
>> + * @return 0 on success, a negative AVERROR on failure. On failure, the
>> + *         packet is unchanged.
>> + */
>> +int av_packet_make_writable(AVPacket *pkt);
>> +
>>  /**
>>   * Convert valid timing fields (timestamps / durations) in a packet from one
>>   * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
>> diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
>> index fe8113ab76..0693ca6f62 100644
>> --- a/libavcodec/avpacket.c
>> +++ b/libavcodec/avpacket.c
>> @@ -652,6 +652,30 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src)
>>      src->size = 0;
>>  }
>>  
>> +int av_packet_make_writable(AVPacket *pkt)
>> +{
>> +    AVBufferRef *buf = NULL;
>> +    int ret;
>> +
>> +    if (pkt->buf && av_buffer_is_writable(pkt->buf))
>> +        return 0;
>> +
>> +    if (!pkt->data)
>> +        return AVERROR(EINVAL);
>> +
>> +    ret = packet_alloc(&buf, pkt->size);
>> +    if (ret < 0)
>> +        return ret;
>> +    if (pkt->size)
>> +        memcpy(buf->data, pkt->data, pkt->size);
>> +
>> +    av_buffer_unref(&pkt->buf);
>> +    pkt->buf  = buf;
>> +    pkt->data = buf->data;
>> +
>> +    return 0;
>> +}
>> +
>>  void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
>>  {
>>      if (pkt->pts != AV_NOPTS_VALUE)
> 
> Why not just call av_buffer_make_writable()? This code seems fine too,
> though.

That would require duplicating all or most of these checks every time
you need to make sure a packet is writable. pkt->buf may be NULL,
pkt->buf may already be writable, pkt->data may be NULL, the like.

I figured a helper function like this where you just call one function
that is "make this packet writable, whatever the current state is" would
come in handy and simplify some parts of the tree. See the two commits i
mentioned in my reply to Paul, or the mpeg4_unpack_bframes patch i sent
last night.
James Almer March 21, 2018, 5:14 p.m. UTC | #5
On 3/19/2018 1:49 PM, James Almer wrote:
> On 3/19/2018 1:32 PM, wm4 wrote:
>> On Mon, 19 Mar 2018 12:42:16 -0300
>> James Almer <jamrial@gmail.com> wrote:
>>
>>> Useful as well to quickly make a packet reference counted when it
>>> isn't already so.
>>>
>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>> ---
>>>  libavcodec/avcodec.h  | 11 +++++++++++
>>>  libavcodec/avpacket.c | 24 ++++++++++++++++++++++++
>>>  2 files changed, 35 insertions(+)
>>>
>>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>>> index a8322fb62a..a78017f1fb 100644
>>> --- a/libavcodec/avcodec.h
>>> +++ b/libavcodec/avcodec.h
>>> @@ -4518,6 +4518,17 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src);
>>>   */
>>>  int av_packet_copy_props(AVPacket *dst, const AVPacket *src);
>>>  
>>> +/**
>>> + * Create a writable reference for the data described by a given packet,
>>> + * avoiding data copy if possible.
>>> + *
>>> + * @param pkt Packet whose data should be made writable.
>>> + *
>>> + * @return 0 on success, a negative AVERROR on failure. On failure, the
>>> + *         packet is unchanged.
>>> + */
>>> +int av_packet_make_writable(AVPacket *pkt);
>>> +
>>>  /**
>>>   * Convert valid timing fields (timestamps / durations) in a packet from one
>>>   * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
>>> diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
>>> index fe8113ab76..0693ca6f62 100644
>>> --- a/libavcodec/avpacket.c
>>> +++ b/libavcodec/avpacket.c
>>> @@ -652,6 +652,30 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src)
>>>      src->size = 0;
>>>  }
>>>  
>>> +int av_packet_make_writable(AVPacket *pkt)
>>> +{
>>> +    AVBufferRef *buf = NULL;
>>> +    int ret;
>>> +
>>> +    if (pkt->buf && av_buffer_is_writable(pkt->buf))
>>> +        return 0;
>>> +
>>> +    if (!pkt->data)
>>> +        return AVERROR(EINVAL);
>>> +
>>> +    ret = packet_alloc(&buf, pkt->size);
>>> +    if (ret < 0)
>>> +        return ret;
>>> +    if (pkt->size)
>>> +        memcpy(buf->data, pkt->data, pkt->size);
>>> +
>>> +    av_buffer_unref(&pkt->buf);
>>> +    pkt->buf  = buf;
>>> +    pkt->data = buf->data;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>  void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
>>>  {
>>>      if (pkt->pts != AV_NOPTS_VALUE)
>>
>> Why not just call av_buffer_make_writable()? This code seems fine too,
>> though.
> 
> That would require duplicating all or most of these checks every time
> you need to make sure a packet is writable. pkt->buf may be NULL,
> pkt->buf may already be writable, pkt->data may be NULL, the like.
> 
> I figured a helper function like this where you just call one function
> that is "make this packet writable, whatever the current state is" would
> come in handy and simplify some parts of the tree. See the two commits i
> mentioned in my reply to Paul, or the mpeg4_unpack_bframes patch i sent
> last night.

I'll apply this later today or tomorrow unless someone objects.
James Almer March 22, 2018, 1:19 a.m. UTC | #6
On 3/21/2018 2:14 PM, James Almer wrote:
> On 3/19/2018 1:49 PM, James Almer wrote:
>> On 3/19/2018 1:32 PM, wm4 wrote:
>>> On Mon, 19 Mar 2018 12:42:16 -0300
>>> James Almer <jamrial@gmail.com> wrote:
>>>
>>>> Useful as well to quickly make a packet reference counted when it
>>>> isn't already so.
>>>>
>>>> Signed-off-by: James Almer <jamrial@gmail.com>
>>>> ---
>>>>  libavcodec/avcodec.h  | 11 +++++++++++
>>>>  libavcodec/avpacket.c | 24 ++++++++++++++++++++++++
>>>>  2 files changed, 35 insertions(+)
>>>>
>>>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>>>> index a8322fb62a..a78017f1fb 100644
>>>> --- a/libavcodec/avcodec.h
>>>> +++ b/libavcodec/avcodec.h
>>>> @@ -4518,6 +4518,17 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src);
>>>>   */
>>>>  int av_packet_copy_props(AVPacket *dst, const AVPacket *src);
>>>>  
>>>> +/**
>>>> + * Create a writable reference for the data described by a given packet,
>>>> + * avoiding data copy if possible.
>>>> + *
>>>> + * @param pkt Packet whose data should be made writable.
>>>> + *
>>>> + * @return 0 on success, a negative AVERROR on failure. On failure, the
>>>> + *         packet is unchanged.
>>>> + */
>>>> +int av_packet_make_writable(AVPacket *pkt);
>>>> +
>>>>  /**
>>>>   * Convert valid timing fields (timestamps / durations) in a packet from one
>>>>   * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
>>>> diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
>>>> index fe8113ab76..0693ca6f62 100644
>>>> --- a/libavcodec/avpacket.c
>>>> +++ b/libavcodec/avpacket.c
>>>> @@ -652,6 +652,30 @@ void av_packet_move_ref(AVPacket *dst, AVPacket *src)
>>>>      src->size = 0;
>>>>  }
>>>>  
>>>> +int av_packet_make_writable(AVPacket *pkt)
>>>> +{
>>>> +    AVBufferRef *buf = NULL;
>>>> +    int ret;
>>>> +
>>>> +    if (pkt->buf && av_buffer_is_writable(pkt->buf))
>>>> +        return 0;
>>>> +
>>>> +    if (!pkt->data)
>>>> +        return AVERROR(EINVAL);
>>>> +
>>>> +    ret = packet_alloc(&buf, pkt->size);
>>>> +    if (ret < 0)
>>>> +        return ret;
>>>> +    if (pkt->size)
>>>> +        memcpy(buf->data, pkt->data, pkt->size);
>>>> +
>>>> +    av_buffer_unref(&pkt->buf);
>>>> +    pkt->buf  = buf;
>>>> +    pkt->data = buf->data;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>  void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
>>>>  {
>>>>      if (pkt->pts != AV_NOPTS_VALUE)
>>>
>>> Why not just call av_buffer_make_writable()? This code seems fine too,
>>> though.
>>
>> That would require duplicating all or most of these checks every time
>> you need to make sure a packet is writable. pkt->buf may be NULL,
>> pkt->buf may already be writable, pkt->data may be NULL, the like.
>>
>> I figured a helper function like this where you just call one function
>> that is "make this packet writable, whatever the current state is" would
>> come in handy and simplify some parts of the tree. See the two commits i
>> mentioned in my reply to Paul, or the mpeg4_unpack_bframes patch i sent
>> last night.
> 
> I'll apply this later today or tomorrow unless someone objects.

Pushed.
diff mbox

Patch

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index a8322fb62a..a78017f1fb 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4518,6 +4518,17 @@  void av_packet_move_ref(AVPacket *dst, AVPacket *src);
  */
 int av_packet_copy_props(AVPacket *dst, const AVPacket *src);
 
+/**
+ * Create a writable reference for the data described by a given packet,
+ * avoiding data copy if possible.
+ *
+ * @param pkt Packet whose data should be made writable.
+ *
+ * @return 0 on success, a negative AVERROR on failure. On failure, the
+ *         packet is unchanged.
+ */
+int av_packet_make_writable(AVPacket *pkt);
+
 /**
  * Convert valid timing fields (timestamps / durations) in a packet from one
  * timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index fe8113ab76..0693ca6f62 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -652,6 +652,30 @@  void av_packet_move_ref(AVPacket *dst, AVPacket *src)
     src->size = 0;
 }
 
+int av_packet_make_writable(AVPacket *pkt)
+{
+    AVBufferRef *buf = NULL;
+    int ret;
+
+    if (pkt->buf && av_buffer_is_writable(pkt->buf))
+        return 0;
+
+    if (!pkt->data)
+        return AVERROR(EINVAL);
+
+    ret = packet_alloc(&buf, pkt->size);
+    if (ret < 0)
+        return ret;
+    if (pkt->size)
+        memcpy(buf->data, pkt->data, pkt->size);
+
+    av_buffer_unref(&pkt->buf);
+    pkt->buf  = buf;
+    pkt->data = buf->data;
+
+    return 0;
+}
+
 void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
 {
     if (pkt->pts != AV_NOPTS_VALUE)